如何从新线程传递数据?

时间:2011-11-09 09:12:16

标签: c# wpf multithreading

我有一个班级:

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 :(得分:0)

如何传递价值?

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"} );

如何更新结果?

捕获UI(主线程)的SynchronizationContext,以指示您何时希望在UI中更新值。捕获的SynchronizationContext引用上的Send / Post方法,以便将消息推送到UI线程。

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 
        }