gpt4 book ai didi

c# - SslStream.WriteAsync "The BeginWrite method cannot be called when another write operation is pending"

转载 作者:太空狗 更新时间:2023-10-30 00:11:24 26 4
gpt4 key购买 nike

异步向客户端写入数据时如何防止这个问题

The BeginWrite method cannot be called when another write operation is pending

我的代码

public async void Send(byte[] buffer)
{
if (buffer == null)
return;
await SslStream.WriteAsync(buffer, 0, buffer.Length);
}

最佳答案

准确理解 await 关键字的作用很重要:

An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off (MSDN - await (C# Reference)).

当您使用一些非空缓冲区调用 Send 时,您将到达

    await SslStream.WriteAsync(buffer, 0, buffer.Length);

使用 await 仅在 Send 方法中阻止执行,但即使 WriteAsync 尚未完成,调用方中的代码仍会继续执行。现在,如果在 WriteAsync 完成之前再次调用 Send 方法,您将得到您发布的异常,因为 SslStream 不允许多个写入操作,并且您发布的代码不会阻止这种情况的发生。

如果你想确保之前的 BeginWrite 已经完成,你必须更改 Send 方法以返回一个 Task

    async Task Send(SslStream sslStream, byte[] buffer)
{
if (buffer == null)
return;

await sslStream.WriteAsync(buffer, 0, buffer.Length);
}

并通过使用 await 来调用它来等待它完成:

    await Send(sslStream, message);

如果您不尝试从多个线程写入数据,这应该可以工作。

还有一些代码可以防止来自多个线程的写操作重叠(如果与您的代码正确集成)。它使用中间队列和异步编程模型 (APM),并且运行速度非常快。您需要调用 EnqueueDataForWrite 来发送数据。

    ConcurrentQueue<byte[]> writePendingData = new ConcurrentQueue<byte[]>();
bool sendingData = false;

void EnqueueDataForWrite(SslStream sslStream, byte[] buffer)
{
if (buffer == null)
return;

writePendingData.Enqueue(buffer);

lock (writePendingData)
{
if (sendingData)
{
return;
}
else
{
sendingData = true;
}
}

Write(sslStream);
}

void Write(SslStream sslStream)
{
byte[] buffer = null;
try
{
if (writePendingData.Count > 0 && writePendingData.TryDequeue(out buffer))
{
sslStream.BeginWrite(buffer, 0, buffer.Length, WriteCallback, sslStream);
}
else
{
lock (writePendingData)
{
sendingData = false;
}
}
}
catch (Exception ex)
{
// handle exception then
lock (writePendingData)
{
sendingData = false;
}
}
}

void WriteCallback(IAsyncResult ar)
{
SslStream sslStream = (SslStream)ar.AsyncState;
try
{
sslStream.EndWrite(ar);
}
catch (Exception ex)
{
// handle exception
}

Write(sslStream);
}

关于c# - SslStream.WriteAsync "The BeginWrite method cannot be called when another write operation is pending",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12611861/

26 4 0
文章推荐: c# - 遍历 List
文章推荐: c# - 空合并运算符