Как передать данные из нового потока? - PullRequest
0 голосов
/ 09 ноября 2011

У меня есть класс:

class ShowComboBoxUpdater
{
    private ComboBox _showComboBox;
    private String _searchString;
    private RequestState _endState;

    public event EventHandler ResultUpdated;

    public string[] getShowList()
    {
        if (_endState.serverQueryResult != null)
            return _endState.serverQueryResult;
        return new string[] { "" };
    }

    public ShowComboBoxUpdater(ComboBox combo, Image refreshImage)
    {
        _showComboBox = combo;
        _refreshImage = refreshImage;
        _endState = new RequestState();
    }

    public void RequestUpdatingComboSource()
    {
        _searchString = _showComboBox.Text;
        Thread t = new Thread(new ThreadStart(MakeServerConnectionThread));
        t.IsBackground = true;
        t.Start();
    }

    private void MakeServerConnectionThread()
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://services.tvrage.com/myfeeds/search.php?show=" + _searchString);
        _endState.request = request;
        IAsyncResult result = request.BeginGetResponse(new AsyncCallback(RequestingThread), _endState);
        ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(ScanTimeoutCallback), _endState, (30 * 1000), true);
    }

    private void RequestingThread(IAsyncResult result)
    {
        RequestState state = (RequestState)result.AsyncState;
        WebRequest request = (WebRequest)state.request;

        HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result);
        Stream bodyStream = response.GetResponseStream();
        StreamReader r = new StreamReader(bodyStream);
        string xmlResponse = r.ReadToEnd().Trim();

        using (StringReader XMLStream = new StringReader(xmlResponse))
        {
            XPathNavigator feed = new XPathDocument(XMLStream).CreateNavigator();
            XPathNodeIterator nodesNavigator = (XPathNodeIterator)feed.Evaluate("descendant::show/name/text()");
            int titlesCount = nodesNavigator.Count;
            string[] titles = new string[titlesCount];
            foreach (XPathNavigator n in nodesNavigator)
            {
                titles[--titlesCount] = n.Value;
            }
            state.serverQueryResult = titles;
            if (this.ResultUpdated != null) this.ResultUpdated(this, new EventArgs());
        }
    }

    private static void ScanTimeoutCallback(object state, bool timedOut)
    {
        if (timedOut)
        {
            RequestState reqState = (RequestState)state;
            if (reqState != null)
                reqState.request.Abort();
        }
    }
}

В моем основном потоке я создаю ShowComboBoxUpdater и подключаю событие ResultUpdate к другому событию. Тогда я вызываю RequestUpdatingComboSource() метод. У меня активировано событие, но как мне получить serverQueryResult? Я знаю, что это там, но все, что я пробую, приводит к тому, что я хочу получить "owned by other thread".

1 Ответ

0 голосов
/ 09 ноября 2011

Как передать значение?

public class MyArgs : EventArgs
    {
        //Declare any specific type here
        public string ResultToPass { get; private set; }
        public MyArgs()
        {
        }
    }

if (this.ResultUpdated != null) this.ResultUpdated(this, new MyArgs(){ResultToPass="Your actual result"} );

Как обновить результат?

Capture SynchronizationContext пользовательского интерфейса (основной поток), чтобы указать, когда вы хотите обновить значение обратно в пользовательском интерфейсе. Метод Send / Post для захваченной ссылки SynchronizationContext, чтобы отправить сообщение в поток пользовательского интерфейса.

public partial class MainWindow : Window 
    { 
        SynchronizationContext UISyncContext; 
        public MainWindow() 
        { 
            InitializeComponent(); 
        } 
        public StartProcessing() 
        { 
            //Let say this method is been called from UI thread. i.e on a button click 
            //capture the current synchronization context 

            UISyncContext=TaskScheduler.FromCurrentSynchronizationContext; 
         }     
       public UpdateResultInUI() 
        { 
            //Let's say this is is the method which user triggers at 
            //some point in time ( with the assumption that we have Myresult in hand) 

            if(UISyncContext!=null) 
                UISyncContext.Send(new SendOrPostCallback(delegate{ PutItInUI }),null); 

            //Use Send method - to send your request synchronously 
            //Use Post method- to send your request asynchronously 
        } 
        void PutItInUI() 
        { 
            //this method help you to put your result in UI/controls 
        } 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...