2011-11-09 36 views
0

我有一个类:如何从新线程传递数据?

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

使用control.Dispatched.Invoke/BeginInvoke将你的调用编组到UI线程 – 2011-11-09 09:15:26

+0

你想获得线程t产生的结果吗? – Tudor

回答

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引用上,以便将消息推送到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 
     } 
+0

已将'UISyncContext = TaskScheduler.FromCurrentSynchronizationContext'更改为'UISyncContext = SynchronizationContext.Current;',它完美地工作。非常感谢你 ! –

+0

很高兴知道。 :) –