我使用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);
其中州包含context
类型为SynchronizationContext
的{{1}}变量设置为SynchronizationContext.Current
它抱怨Post需要两个参数,第二个是Object state
。插入state
会出现错误
Argument `#1' cannot convert `anonymous method' expression to type `System.Threading.SendOrPostCallback' (CS1503) (Core.Droid)
答案 0 :(得分:2)
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);
答案 1 :(得分: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类中。