在.net 2.0中从后台调用UI线程上的方法
本文关键字:线程 UI 方法 调用 后台 net | 更新日期: 2023-09-27 18:00:25
我正在使用MonoDevelop(.net 2.0)开发iOS和Android应用程序。我使用BeginGetResponse和EndGetResponse在后台线程中异步执行Web请求。
IAsyncResult result = request.BeginGetResponse(new AsyncCallback(onLogin), state);
然而,回调onLogin
似乎仍然在后台线程上运行,不允许我与UI交互。我该如何解决此问题?
可以看到,有Android和iOS特定的解决方案,但想要一个跨平台的解决方案。
编辑:根据mhutch的答案,我已经得到了:
IAsyncResult result = request.BeginGetResponse(o => {
state.context.Post(() => { onLogin(o); });
}, state);
其中state包含SynchronizationContext
类型的context
变量,设置为SynchronizationContext.Current
它抱怨Post需要两个参数,第二个是Object state
。插入state
会产生错误
Argument `#1' cannot convert `anonymous method' expression to type `System.Threading.SendOrPostCallback' (CS1503) (Core.Droid)
Xamarin.iOS和Xamarin。Android为GUI线程设置了SynchronizationContext
。
这意味着您从GUI线程获得SynchronizationContext.Current
,并将其传递给回调(例如,通过状态对象或在lambda中捕获)。然后,您可以使用上下文的Post
方法来调用主线程上的内容。
例如:
//don't inline this into the callback, we need to get it from the GUI thread
var ctx = SynchronizationContext.Current;
IAsyncResult result = request.BeginGetResponse(o => {
// calculate stuff on the background thread
var loginInfo = GetLoginInfo (o);
// send it to the GUI thread
ctx.Post (_ => { ShowInGui (loginInfo); }, null);
}, state);
我不确定这是否适用于Mono,但我通常在WinForm应用程序上这样做。假设您想要执行方法X()
。然后:
public void ResponseFinished() {
InvokeSafe(() => X()); //Instead of just X();
}
public void InvokeSafe(MethodInvoker m) {
if (InvokeRequired) {
BeginInvoke(m);
} else {
m.Invoke();
}
}
当然,这是在Form类中。