SynchronizationContext.Post到UI方法

我正在使用Web服务,因此我需要扩展会话长度/重新连接并获取大型数据集等。有时这可能很长,所以我希望它在一个单独的线程中异步更新UI。

我似乎无法理解使用synchronizationContext在我的UI线程上调用方法。 我有它,我已经将我的UIThread上下文传递给我的线程,现在我想在UI线程上更新一些标签等。 我已经阅读了大量的post,但似乎没有解释如何简单地将一些参数传递回方法,或者他们可能会这样做,但我太累了/傻到看到它。

//在主UI线程上

public void updateConnStatus(string conn_name, bool connected) { switch (conn_name) { case "Conn" : if (connected == true){ //do something} break; 

//在单独的线程上

 uiContext.Post( //something to do with delegates in here that eludes me ); 

如果有人可以简单地解释我如何将sendOrPostCallBack链接到原始方法,我将非常感激。

谢谢

编辑:

我设法让代码运行并尝试触发事件,它填充我的自定义eventArgs好,但要么说它没有实例化updateUIConnStatus,需要更多的调查:o

 public void updateUIThread(string conn, bool connected) { uiContext.Post(new SendOrPostCallback((o) => { updateConnStatus(this, new MyEventArgs(conn, connected)); }), null); } public class MyEventArgs : EventArgs { private T _val1; private U _val2; public MyEventArgs(T value1, U value2) { _val1 = value1; _val2 = value2; } public T val1 { get { return _val1;} } public U val2 { get {return _val2;} } } public event EventHandler<MyEventArgs> updateConnStatus = Delegate {}; 

//在UI Thread Now上

  public void updateConnStatus(object sender, MyEventArgs e) { switch (e.val1) { case "Conn1" : if (e.val2 == true) { 

您需要SendOrPostCallback类型的委托。 这很尴尬,它只需要一个类型为object的参数。 你肯定应该看看.NET 4中提供的Task <>类来使这更容易。 或者使用lambda,如下所示:

  string conn_name = "foo"; uiContext.Post(new SendOrPostCallback((o) => { updateConnStatus(conn_name, true); }), null); 

{braces}之间的代码在UI线程上执行。

通常,您在UI线程上创建类型的实例(例如ViewModels),因此您只需将SynchronizationContext或TaskScheduler(优选的恕我直言)保存到私有字段,然后在需要时进行比较…

 private readonly SynchronizationContext _syncContext = SynchronizationContext.Current; private readonly TaskScheduler _scheduler = TaskScheduler.Current; void OnSomeEvent(object sender, EventArgs e) { if (_syncContext != SynchronizationContext.Current) { // Use Send if you need to get something done as soon as possible. // We'll be polite by using Post to wait our turn in the queue. _syncContext.Post(o => DoSomething(), null); return; } // Call directly if we are already on the UI thread DoSomething(); } void OnSomeOtherEvent(object sender, MyEventArgs e) { var arg1 = e.Arg1; // "Hello " var arg2 = e.Arg2; // {"World", "!"}; // Process args in the background, and then show the result to the user... // NOTE: We don't even need to check the context because we are passing // the appropriate scheduler to the continuation that shows a MessageBox. Task.Factory.StartNew(() => ReturnSomething(arg1, arg2)) .ContinueWith(t => MessageBox.Show(t.Result), _scheduler); } void DoSomething() { MessageBox.Show("Hello World!"); } string ReturnSomething(string s, IEnumerable list) { return s + list.Aggregate((c, n) => c + n); }