我需要从ASP.NET核心API中控制摄像头,所有通信都是通过pInvoke dll进行的。 在文档中明确指出
要创建用户线程并从该线程访问摄像头,请务必执行CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)在线程的开头和最后的CoUnInitialize()。
e.g
CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
EdsSendCommand(camera, kEdsCameraCommand_TakePicture, 0);
CoUninitialize()
我的相机服务在winforms应用程序(STA)中运行,但是当我将其移动到我的API时,回调不会在事件发生时触发。 我已经尝试在STA线程中包装组件并设置执行循环,但回调仍然不会触发。
我想我可能需要一个消息泵,但我不确定它应该如何工作。
非工作代码:
Thread handlerThread;
handlerThread = new Thread(STAThreadLoop);
handlerThread.SetApartmentState(ApartmentState.STA);
handlerThread.Start();
并在线程循环中
void STAThreadLoop()
{
logger.LogInformation("Starting STAThreadLoop...");
lock (handlerThreadLock)
{
handlerSignal.Set();
while (!exitHandlerThreadLoop)
{
Thread.Yield();
Monitor.Wait(handlerThreadLock);
if (handlerThreadAction != null)
{
try
{
handlerThreadAction();
}
catch (Exception ex)
{
logger.LogError(ex, "Error executing action on STA thread: {ThreadName}", Thread.CurrentThread.Name);
}
}
Monitor.Pulse(handlerThreadLock);
}
}
}
然后创建组件
RunSTAAction(() =>
{
handler = new SDKHandler(loggerFactory.CreateLogger<SDKHandler>());
});
和转换到STA线程的方法
void RunSTAAction(Action action)
{
if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
{
lock (handlerThreadLock)
{
handlerThreadAction = action;
Monitor.Pulse(handlerThreadLock);
Monitor.Wait(handlerThreadLock);
}
}
else
{
action();
}
}
更新:这实际上已修复,请参阅下面的答案
答案 0 :(得分:1)
实际上,我们创建了ThreadAffinityTaskScheduler的实例,并将WaitHelpers.WaitWithMessageLoop作为等待函数传递。
ThreadAffinityTaskScheduler messageScheduler;
messageScheduler = new ThreadAffinityTaskScheduler(3, staThreads: true, waitHelper: WaitHelpers.WaitWithMessageLoop);
messageScheduler.Run(new Action(STAThreadLoop), CancellationToken.None);