相关疑难解决方法(0)

CoWaitForMultipleHandles API的行为与记录不符

这是由我正在研究的另一个问题引发的.阅读可能太长了,所以请耐心等待.

显然,在MSDN CoWaitForMultipleHandles没有记录的行为.

下面的代码(基于原始问题)是一个控制台应用程序,它启动一个带有测试Win32窗口的STA线程并尝试发布并抽取一些消息.它做了三个不同的测试CoWaitForMultipleHandles,都没有 COWAIT_WAITALL标志.

测试#1旨在验证这一点:

COWAIT_INPUTAVAILABLE如果设置,如果队列输入存在,则对CoWaitForMultipleHandles的调用将返回S_OK,即使已使用对另一个函数(如PeekMessage)的调用看到(但未删除)输入.

这不会发生,CoWaitForMultipleHandles阻塞并且在发出等待句柄之前不会返回.我不认为任何未决的消息应被视为输入(与同MWMO_INPUTAVAILABLEMsgWaitForMultipleObjectsEx,它按预期工作).

测试#2旨在验证这一点:

COWAIT_DISPATCH_WINDOW_MESSAGES允许从ASTA或STA中的CoWaitForMultipleHandles分派窗口消息.ASTA中的默认值是没有调度的窗口消息,STA中的默认值只是一小部分特殊的消息调度.该值在MTA中没有意义,将被忽略.

这也不起作用.当CoWaitForMultipleHandles仅使用COWAIT_DISPATCH_WINDOW_MESSAGES标志调用时,它会立即返回错误CO_E_NOT_SUPPORTED(0x80004021).如果它是一个组合COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS,则呼叫阻止但不抽取任何消息.

测试#3演示了我可以CoWaitForMultipleHandles使用调用线程的Windows消息队列的唯一方法.它是一个组合COWAIT_DISPATCH_WINDOW_MESSAGES | COWAIT_DISPATCH_CALLS | COWAIT_INPUTAVAILABLE.这确实是泵送和发送消息,尽管显然它是一种无证件的行为.

测试代码(可立即运行的控制台应用程序):

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleTestApp
{
    static class Program
    {
        // Main 
        static …
Run Code Online (Sandbox Code Playgroud)

.net c# windows com winapi

10
推荐指数
1
解决办法
5106
查看次数

任务TPL的Thread.Interrupt等价物

一些背景知识:我的C#代码调用了一些阻塞等待的非托管代码(C++).阻塞等待,但是,可报警(像Thread.Sleep-我想它调用WaitForSingleObjectExbAlertable TRUE下盖); 我肯定知道它是警觉的,因为它可以被"唤醒" QueueUserAPC.

如果我可以简单地使用托管线程,我只会调用阻塞方法,然后Thread.Interrupt在需要它时退出时使用"唤醒"线程; 这样的事情:

void ThreadFunc() {
    try {
           Message message;
           comObject.GetMessage(out message);
           //....
     }
     catch (ThreadInterruptedException) {
        // We need to exit
        return;
     }
}

var t - new Thread(ThreadFunc);
//....
t.Interrupt();
Run Code Online (Sandbox Code Playgroud)

(注意:我没有使用这个代码,但据我所知,它可能适用于这种特殊情况(在我的控制之外的非托管代码中可警告等待).我正在寻找的是最好的相当于(或更好的替代!)在TPL中的这个.

但是我必须使用TPL(任务而不是托管的线程),并且非托管方法不受我的控制(WaitForMultipleObjectEx例如,当我向事件发出信号时,我无法修改它以调用它并使其返回).

我正在寻找一个Thread.Interrupt等价的任务(将在底层线程上发布APC的东西).AFAIK,CancellationTokens要求代码是"任务感知",并且不要使用这种技术,但我不确定:发生了什么,我想知道,如果任务执行了Thread.Sleep(我知道有一个Task.Wait,但它只是为了拥有一个可以警告的非任务等待的例子,可以取消吗?

我的假设是错的(我的意思是,我可以只使用CT,一切都会起作用吗?但是如何?).

如果没有这样的方法......我愿意接受建议.我真的想避免混合线程和任务,或使用P/Invoke,但如果没有别的办法,我仍然希望以"最干净"的方式做到这一点(这意味着:没有粗鲁的中止,并且"Tasky":))

编辑:

对于那些好奇的人,我已经"确认"Thread.Interrupt可以在我的情况下工作,因为它调用QueueUserAPC.InterruptInternal然后Thread::UserInterrupt,它调用AlertAPC排队.它实际上非常聪明,因为它允许您休眠/等待然后唤醒线程而无需使用其他同步原语.

我只需要找到遵循相同流程的TPL原语

.net c# multithreading task-parallel-library

8
推荐指数
1
解决办法
642
查看次数

等待任何线程完成,而不是全部

我开始多线程,并想知道什么时候任何的然后完成.我知道以下代码:

foreach (Thread t in threads)
    t.Join();
Run Code Online (Sandbox Code Playgroud)

但它只会等待所有线程在一起.那太晚了.我需要知道一个线程何时完成,即使其他线程仍在运行.我正在寻找相当于WaitAny线程的东西.但是我无法将代码添加到我正在监视的所有线程中,因此使用信号或其他同步对象不是一种选择.

一些澄清:我正在开发一个记录/跟踪工具,它应该记录应用程序的活动.我可以在线程启动时插入日志语句,但是我不能在线程的每个可能的方式上插入日志语句(多个退出点,异常等).所以我想注册新线程,然后在完成写入日志条目时收到通知.我可以Join在每个线程上异步,但这意味着每个受监控线程的第二个线程可能看起来有点开销.线程是通过各种方式使用的,是它BackgroundWorker,Task或池中的线程.从本质上讲,它是一个线程,我想知道它什么时候完成.确切的线程机制由应用程序定义,而不是日志记录解决方案.

c# multithreading synchronization

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