如何使委托线程成为STA
我看到了一些围绕这个主题的讨论,并得出结论:这是不可能的。我应该使用线程,将其设为 STA,当我需要返回结果时,将主线程与创建的线程连接起来。这可以工作,但它不是一个理想的解决方案,因为使用委托我可以实现纯异步行为(使用回调)。所以,首先——就在我开始实现我自己的 Future 类(如 Java 中)之前;有没有更好的方法使用委托来实现这一目标?
private delegate String DelegateFoo(String[] input);
private String Foo(String[] input){
// do something with input
// this code need to be STA
// below code throws exception .. that operation is invalid
// Thread.CurrentThread.SetApartmentState(ApartmentState.STA)
return "result";
}
private void callBackFoo(IAsyncResult iar){
AsyncResult result = (AsyncResult)iar;
DelegateFoo del = (DelegateFoo)result.AsyncDelegate;
String result = null;
try{
result = del.EndInvoke(iar);
}catch(Exception e){
return;
}
DelegateAfterFooCallBack callbackDel = new DelegateAfterFooCallBack (AfterFooCallBack);
// call code which should execute in the main UI thread.
if (someUIControl.InvokeRequired)
{ // execute on the main thread.
callbackDel.Invoke();
}
else
{
AfterFooCallBack();
}
}
private void AfterFooCallBack(){
// should execute in main UI thread to update state, controls and stuff
}
I have see some discussion around this topic and concluded that it is not possible. I should use Threads, make it STA and when I need result back, join main thread with the created thread. This can work but it is not an ideal solution as using delegates I can achieve pure asynchronous behavior (using callback). So, to square one - just before I start implementing my own Future class (as in Java); Is there a better way to achieve this using delegates?
private delegate String DelegateFoo(String[] input);
private String Foo(String[] input){
// do something with input
// this code need to be STA
// below code throws exception .. that operation is invalid
// Thread.CurrentThread.SetApartmentState(ApartmentState.STA)
return "result";
}
private void callBackFoo(IAsyncResult iar){
AsyncResult result = (AsyncResult)iar;
DelegateFoo del = (DelegateFoo)result.AsyncDelegate;
String result = null;
try{
result = del.EndInvoke(iar);
}catch(Exception e){
return;
}
DelegateAfterFooCallBack callbackDel = new DelegateAfterFooCallBack (AfterFooCallBack);
// call code which should execute in the main UI thread.
if (someUIControl.InvokeRequired)
{ // execute on the main thread.
callbackDel.Invoke();
}
else
{
AfterFooCallBack();
}
}
private void AfterFooCallBack(){
// should execute in main UI thread to update state, controls and stuff
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是不可能的。委托的 BeginInvoke() 方法始终使用线程池线程。并且TP线程始终是MTA,无法更改。要获得 STA 线程,您必须创建一个 Thread 并在启动它之前调用其 SetApartmentState() 方法。该线程还必须泵送消息循环Application.Run()。 COM 对象仅在该线程中创建其实例时才使用它。
不确定您要做什么,但尝试对一段非线程安全的代码进行多线程处理是行不通的。 COM 强制执行这一点。
It is not possible. A delegate's BeginInvoke() method always uses a threadpool thread. And TP threads always are MTA, that cannot be changed. To get an STA thread, you must create a Thread and call its SetApartmentState() method before starting it. This thread must also pump a message loop, Application.Run(). The COM object only uses it when its instance was created in that thread.
Not sure what you are trying to do, but trying to multi-thread a chunk of code that is not thread-safe just can't work. COM enforces that.