我有一个简单的.NET6WinForms应用程序,它创建一个带有一个菜单项的系统托盘图标:Exit.该应用程序生成一个异步任务来管理从Windows服务接收和记录消息的命名管道.如果用户单击Exit菜单项,事件处理程序将取消令牌,但是命名管道WaitForConnectionsAsync调用不会识别该取消.

我已经try 了启动序列的许多变体.在本例中,我认为命名管道线程可能需要configureAwait(false),但它仍然不起作用.围绕调试消息的散布显示UI部分确实正确地退出并且令牌is被取消,但是命名管道类从未退出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中没有什么有趣的东西--它只是创建图标和菜单,退出事件处理程序处理一些内部对象,然后调用上面所示的Program.Exit.

对于MessageServer类,我知道所有的代码都是正确和有效的,我已经在许多其他项目(example)中使用过它,多年来我在许多场景中使用过异步/等待和取消令牌,包括复杂的多线程WPF应用程序.我认为图片中的WinForms有些不同……

推荐答案

根据WaitForConnectionAsync上的 comments :

仅当NamedPipeServerStream对象是使用管道选项值PipeOptions.Achronous创建的,或者如果取消发生在调用WaitForConnectionAsync方法之前,使用取消令牌的取消请求才会起作用.

试试这个:

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

Csharp相关问答推荐

使用C#中的Shape API从Azure目录获取所有用户

TDLib与机器人共享电话号码

C#中使用BouncyCastle计算CMac

如果存在对CodeAnalysis.CSharp的引用,则不能引用netStandard2.0库

实体框架核心上是否支持使用NPGSQL的字符串聚合?

图形API基于appid列表检索多个应用程序

.NET 8 Web-API返回空列表

如何测量在使用UTF8而不是C#中的UTF16编码字符串时内存使用量的增长

Azure函数中实体框架核心的依赖注入

MigraDoc文档

如何实现有条件的自定义Json转换器隐藏属性

如何在.NET MAUI中最大化GraphicsView的大小?

为什么C#/MSBuild会自发地为不同的项目使用不同的输出路径?

如何使用.NET Aspire从Blazor应用程序与GRPC API通信?

我想根据姓氏按字母顺序对包含150行徽章编号、姓氏、名字、地址等的文件进行排序.e

为什么当我try 为玩家角色设置动画时,没有从文件夹中拉出正确的图像?

忽略Visual Studio代码中的StyleCop规则

如何在.NET Core 8中自定义标识用户模型

用于分钟和秒验证的MudTextfield的正则表达式掩码

为什么Visual Studio 2022建议IDE0251将我的方法设置为只读?