gpt4 book ai didi

c# - 卡在管道上的 WaitForConnectionAsync()

转载 作者:行者123 更新时间:2023-11-30 16:52:28 27 4
gpt4 key购买 nike

<分区>

我正在通过命名管道与另一个进程通信。管道服务器用C#实现,客户端用C编写。服务器是一个WPF应用程序。

我需要创建一个 NamedPipeServerStream并等待(同步)最多 1 秒让客户端连接。然后我需要知道客户端是否连接。

作为NamedPipeServerStream取消/超时等待客户端连接的唯一方法是通过其异步 WaitForConnectionAsync方法 - 它需要一个 CancellationToken - 我已经实现了我认为是这样的同步等待:

public bool WaitOneSecondForClientConnect()
{
bool result = false;
try
{
result = WaitForConnectionAsyncSyncWrapper().Result;
}
catch (AggregateException e)
{
log.Write("Error waiting for pipe client connect: " + e.InnerException.Message);
}
return result;
}

private async Task<bool> WaitForConnectionAsyncSyncWrapper()
{
CancellationTokenSource cts = new CancellationTokenSource(1000);
await pipe.WaitForConnectionAsync(cts.Token);
return pipe.IsConnected;
}

管道定义如下:NamedPipeServerStream(pipeName, PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 1, 1);WaitOneSecondForClientConnect()函数在 UI 线程上运行。

应该使其同步的是访问异步 WaitForConnectionAsyncSyncWrapper()函数的 Result Task<bool> 上的属性(property)它返回。为了访问结果,异步函数必须完全返回,它不能执行 return pipe.IsConnected行直到await pipe.WaitForConnectionAsync(cts.Token);之后功能恢复已经完成。至少这是我的理解。

所以问题是:虽然客户端程序说它打开了我服务器的管道(当然在上面的代码执行之前已经创建好了),WaitOneSecondForClientConnect()永远不会回来。如果我闯入服务器,它就在这一行:result = WaitForConnectionAsyncSyncWrapper().Result; .

所以我猜它正在等待任务的结果可用,这应该是pipe.IsConnected的值如果客户端在 1 秒内连接,或者它应该抛出 AggregateException当我访问它时如果 await已完成,因为 token 已被取消(1 秒后)。但它只是完全挂起。

另一方面,如果我在开始之前取消 token ,例如通过放置 Thread.Sleep(2000);就在打电话之前 await pipe.WaitForConnectionAsync(cts.Token); ,然后连接被成功取消(我认为它甚至没有尝试启动,因为 token 已经被取消) - 访问 Result属性抛出 AggregateException等等……

有几点需要注意。

  • 如果我替换WaitOneSecondForClientConnect()的内容与标准同步pipe.WaitForConnection(); ,它每次都有效 -即客户端连接,函数返回。
  • 在我编写的一个测试程序中,最初是为了让异步/同步的东西正常工作,以这种同步-异步方式连接每次都能正常工作。这是一个控制台程序,而不是我的真实程序 WPF。下面列出了测试程序的相关代码。
  • 上面发布的代码实际上已经运行了几次,可能失败了 30-40 次。
  • 如果我的客户没有打开我的管道,我的“真实”代码仍然挂起,而我的测试代码等待指定的时间段然后打印“连接失败”。正如预期的那样(见下文)——这正是我的真实代码中应该发生的行为。

有效的测试代码:

var pipe = new NamedPipeServerStream("SemiUsefulPipe_" + pid.ToString() + "ctest", PipeDirection.Out, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous, 1, 1);

// ... dll containing pipe client is injected in client process at this point.

try
{
var result = ConnectAsync(pipe).Result;
}
catch (AggregateException)
{
Console.WriteLine("Connection failed.");
}

...

private static async Task<bool> ConnectAsync(NamedPipeServerStream pipe)
{
CancellationTokenSource cts = new CancellationTokenSource(1000);
await pipe.WaitForConnectionAsync(cts.Token);
return pipe.IsConnected;
}

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com