相关疑难解决方法(0)

StaTaskScheduler和STA线程消息泵送

TL; DR:运行任务中的死锁StaTaskScheduler.长版:

我使用的是StaTaskSchedulerParallelExtensionsExtras中通过平行小组,举办由第三方提供的一些遗留STA COM对象.StaTaskScheduler实现细节的描述如下:

好消息是TPL的实现能够在MTA或STA线程上运行,并考虑到底层API的相关差异,如WaitHandle.WaitAll(当方法提供多个等待句柄时,它只支持MTA线程).

我认为这意味着TPL的阻塞部分将使用等待API来提供消息,例如CoWaitForMultipleHandles,以避免在STA线程上调用时出现死锁情况.

在我的情况下,我相信发生以下情况:进程内STA COM对象A调用进程外对象B,然后期望从B通过回调作为传出调用的一部分.

以简化形式:

var result = await Task.Factory.StartNew(() =>
{
    // in-proc object A
    var a = new A(); 
    // out-of-proc object B
    var b = new B(); 
    // A calls B and B calls back A during the Method call
    return a.Method(b);     
}, CancellationToken.None, TaskCreationOptions.None, staTaskScheduler);
Run Code Online (Sandbox Code Playgroud)

问题是,a.Method(b)永远不会回来.据我所知,这是因为内部阻塞等待BlockingCollection<Task>不会引发消息,因此我对引用语句的假设可能是错误的.

EDITED相同的代码工作测试WinForms应用程序的UI线程上执行时(即,提供TaskScheduler.FromCurrentSynchronizationContext()的,而不是staTaskSchedulerTask.Factory.StartNew).

解决这个问题的正确方法是什么?我应该实现一个自定义同步上下文,它将显式地使用消息CoWaitForMultipleHandles …

.net c# com task-parallel-library async-await

27
推荐指数
2
解决办法
9314
查看次数

哪些现有的 CLR 主机不提供托管线程和非托管线程之间的一对一映射?

我知道我应该依赖于有托管和非托管线程之间的一个一对一的映射。从MSDN

操作系统 ThreadId 与托管线程没有固定的关系,因为非托管主机可以控制托管线程和非托管线程之间的关系。具体来说,一个复杂的主机可以使用 Fiber API 来针对同一个操作系统线程调度多个托管线程,或者在不同的操作系统线程之间移动一个托管线程。

但在现实生活中,这样的 CLR 主机存在吗?(如果是这样,它们是什么?)我刚刚回答了一个相关的问题,我想知道我的建议对于那个特定案例有多么糟糕。

.net c# clr winapi multithreading

4
推荐指数
1
解决办法
329
查看次数

如何提取COM消息?

我想等待WebBrowser控件完成导航.所以我创建一个事件,然后我想等待它被设置:

procedure TContoso.NavigateToEmpty(WebBrowser: IWebBrowser2);
begin
   FEvent.ResetEvent;
   WebBrowser.Navigate2('about:blank'); //Event is signalled in the DocumentComplete event

   Self.WaitFor;
end;
Run Code Online (Sandbox Code Playgroud)

然后我在事件中设置DocumentComplete事件:

procedure TContoso.DocumentComplete(ASender: TObject; const pDisp: IDispatch; const URL: OleVariant);
var
    doc: IHTMLDocument2;
begin
    if (pDisp <> FWebBrowser.DefaultInterface) then
    begin
       //This DocumentComplete event is for another frame
       Exit;
    end;

    //Set the event that it's complete
    FEvent.SetEvent;
end;
Run Code Online (Sandbox Code Playgroud)

问题在于如何等待此事件发生.

等待它

第一反应是等待事件被触发:

procedure TContoso.WaitFor;
begin
   FEvent.WaitFor;
end;
Run Code Online (Sandbox Code Playgroud)

问题在于DocumentComplete事件永远不会触发,因为应用程序永远不会空闲,以允许COM事件通过.

忙碌的睡眠等待

我的第一反应是忙着睡觉,等待一面旗帜:

procedure TContoso.NavigateToEmpty(WebBrowser: IWebBrowser2);
begin
   FIsDocumentComplete := …
Run Code Online (Sandbox Code Playgroud)

windows delphi com events winapi

3
推荐指数
1
解决办法
372
查看次数