在.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)

在.net 2.0中从后台调用UI线程上的方法

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类中。