我有一个简单的.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有些不同……