取消令牌无法工作,NET6 WinForms应用程序

ryoqjall  于 2023-05-01  发布在  其他
关注(0)|答案(1)|浏览(136)

我有一个简单的。NET 6 WinForms应用程序,它创建一个带有一个菜单项的系统托盘图标:退出。应用将派生一个异步任务来管理从Windows服务接收和记录消息的命名管道。如果用户单击Exit菜单项,事件处理程序将取消令牌,但是命名管道WaitForConnectionsAsync调用无法识别取消。
我已经尝试了启动顺序的许多变化。在本例中,我认为命名管道线程可能需要configureAwait(false),但它仍然不起作用。散布在调试消息上的情况表明UI部分确实正确退出,并且令牌 * 被取消,但是命名管道类永远不会退出WaitForConnectionAsync调用。

Program.cs

internal static class Program
{
    private static SystemTrayApp trayApp = null;
    private static CancellationTokenSource ctsMessageServer = new();

    [STAThread] 
    static void Main() 
        => MainAsync().GetAwaiter().GetResult();

    static async Task MainAsync()
    {
        List<Task> tasks = new();

        tasks.Add(Task.Run(() =>
        {
            ApplicationConfiguration.Initialize();
            trayApp = new SystemTrayApp();
            Application.Run(trayApp);
        }));

        tasks.Add(Task.Run(async Task () =>
        {
            await MessageServer.RunServer(ctsMessageServer.Token).configureAwait(false);
        }));

        await Task.WhenAll(tasks);
        Environment.Exit(0);
    }

    public static void Exit()
    {
        ctsMessageServer.Cancel();
        trayApp.Dispose();
        Application.Exit();
    }
}

MessageServer。cs(部分)

internal static class MessageServer
{
    private static readonly string pipeServerName = "fubar";
    private static readonly string separatorControlCode = "\u0014";

    public static async Task RunServer(CancellationToken cancellationToken)
    {
        try
        {
            while(!cancellationToken.IsCancellationRequested)
            {
                using var server = new NamedPipeServerStream(pipeServerName, PipeDirection.In);

                await server.WaitForConnectionAsync(cancellationToken);
                cancellationToken.ThrowIfCancellationRequested();

    // omitted the rest, never reaches the line above
    // below: reading the data, disconnect, catch blocks, etc.

SystemTrayApp中没有什么有趣的东西--它只是创建图标和菜单,Exit事件处理程序处理一些内部对象,然后调用上面所示的Program.Exit
对于MessageServer类,我知道所有代码都是正确的,并且可以工作,我在许多其他项目(example)中使用过它,多年来我在许多场景中使用过async/await和取消令牌,包括复杂的多线程WPF应用程序。我假设图片中的WinForms有所不同。..

cxfofazt

cxfofazt1#

根据WaitForConnectionAsync上的备注:
使用取消令牌的取消请求仅在NamedPipeServerStream对象是使用PipeOptions的管道选项值创建的情况下才有效。Asynchronous或如果取消发生在调用WaitForConnectionAsync方法之前。
试试这个:

using var server = new NamedPipeServerStream("", PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

相关问题