我正在使用Web服务,因此我需要扩展会话长度/重新连接并获取大型数据集等。有时这可能很长,所以我希望它在一个单独的线程中异步更新UI。
我似乎无法使用synchronizationContext在我的UI线程上调用方法。我有它,我已经将我的UIThread上下文传递给我的线程,现在我想更新UI线程上的一些标签等。我已经阅读了大量的帖子,但似乎没有解释如何简单地将一些参数传递回方法,或者他们可能会这样做,但是我太累了/太愚蠢而没看过它。
//在主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<String, Boolean>(conn, connected)); }), null);
}
public class MyEventArgs<T, U> : 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<String, Boolean>> updateConnStatus = Delegate {};
//在UI Thread Now上
public void updateConnStatus(object sender, MyEventArgs<String,Boolean> e)
{
switch (e.val1)
{
case "Conn1" :
if (e.val2 == true)
{
答案 0 :(得分:15)
您需要SendOrPostCallback类型的委托。这很尴尬,只需要一个 object 类型的参数。你肯定应该看看任务&lt;&gt; .NET 4中提供的类可以使这更容易。或者使用lambda,如下所示:
string conn_name = "foo";
uiContext.Post(new SendOrPostCallback((o) => {
updateConnStatus(conn_name, true);
}), null);
{braces}之间的代码在UI线程上执行。
答案 1 :(得分:6)
通常,您在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<string>.Factory.StartNew(() => ReturnSomething(arg1, arg2))
.ContinueWith(t => MessageBox.Show(t.Result), _scheduler);
}
void DoSomething() { MessageBox.Show("Hello World!"); }
string ReturnSomething(string s, IEnumerable<string> list)
{
return s + list.Aggregate((c, n) => c + n);
}