0

我正在使用 MonoDevelop (.net 2.0) 开发 iOS 和 Android 应用程序。我使用 BeginGetResponse 和 EndGetResponse 在后台线程中异步执行 webrequest。

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 包含类型设置为的context变量SynchronizationContextSynchronizationContext.Current

它抱怨 Post 需要两个参数,第二个是Object state. 插入state会出现错误

Argument `#1' cannot convert `anonymous method' expression to type `System.Threading.SendOrPostCallback' (CS1503) (Core.Droid)
4

2 回答 2

2

Xamarin.iOS 和 Xamarin.Android 都SynchronizationContext为 GUI 线程设置了一个。

这意味着您SynchronizationContext.Current从 GUI 线程获取并将其传递给您的回调(例如,通过状态对象或在 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);
于 2013-02-22T17:07:53.587 回答
0

我不确定这是否适用于 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 类中。

于 2013-02-21T08:51:18.927 回答