- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
美好的一天。我使用 UdpClient
并对其进行包装。
为了阅读我有异步方法:
private async Task<byte[]> Receive(UdpClient client, CancellationToken breakToken)
{
// Выход из async, если произошёл CancellationRequest
breakToken.ThrowIfCancellationRequested();
UdpReceiveResult result;
try
{
result = await client.ReceiveAsync().WithCancellation(breakToken);
}
catch(OperationCanceledException)
{
// Штатная ситуация ручной остановки Task-а
}
return result.Buffer;
}
WithCancellation
是我提前终止的扩展方法:
public static async Task<T> WithCancellation<T>(
this Task<T> task, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(
s => ((TaskCompletionSource<bool>)s).TrySetResult(true),
tcs))
if (task != await Task.WhenAny(task, tcs.Task))
throw new OperationCanceledException(cancellationToken);
return await task;
}
在手动读取停止后,当我调用 Dispose
时,发生了 System.ObjectDisposedException
。 调用堆栈
:
> System.dll!System.Net.Sockets.UdpClient.EndReceive(System.IAsyncResult asyncResult, ref System.Net.IPEndPoint remoteEP) Unknown
System.dll!System.Net.Sockets.UdpClient.ReceiveAsync.AnonymousMethod__64_1(System.IAsyncResult ar) Unknown
mscorlib.dll!System.Threading.Tasks.TaskFactory<System.Net.Sockets.UdpReceiveResult>.FromAsyncCoreLogic(System.IAsyncResult iar, System.Func<System.IAsyncResult, System.Net.Sockets.UdpReceiveResult> endFunction, System.Action<System.IAsyncResult> endAction, System.Threading.Tasks.Task<System.Net.Sockets.UdpReceiveResult> promise, bool requiresSynchronization) Unknown
mscorlib.dll!System.Threading.Tasks.TaskFactory<System.Net.Sockets.UdpReceiveResult>.FromAsyncImpl.AnonymousMethod__0(System.IAsyncResult iar) Unknown
System.dll!System.Net.LazyAsyncResult.Complete(System.IntPtr userToken) Unknown
System.dll!System.Net.ContextAwareResult.CompleteCallback(object state) Unknown
mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) Unknown
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) Unknown
System.dll!System.Net.ContextAwareResult.Complete(System.IntPtr userToken) Unknown
System.dll!System.Net.LazyAsyncResult.ProtectedInvokeCallback(object result, System.IntPtr userToken) Unknown
System.dll!System.Net.Sockets.BaseOverlappedAsyncResult.CompletionPortCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* nativeOverlapped) Unknown
mscorlib.dll!System.Threading._IOCompletionCallback.PerformIOCompletionCallback(uint errorCode, uint numBytes, System.Threading.NativeOverlapped* pOVERLAP) Unknown
如果我理解正确,ReceiveAsync
中的错误根源,准确地说是我停止它的方法。但我不知道如何修复它。
我必须怎么做才能纠正这个错误?
Update after usr comment:
private async Task<byte[]> Receive(UdpClient client, CancellationToken breakToken)
{
// Выход из async, если произошёл CancellationRequest
breakToken.ThrowIfCancellationRequested();
UdpReceiveResult result;
try
{
result = await client.ReceiveAsync().WithCancellation(breakToken);
}
catch(OperationCanceledException)
{
// Штатная ситуация ручной остановки Task-а
}
catch(ObjectDisposedException) { }
return result.Buffer;
}
和Dispose
调用:
public void Dispose()
{
this.cancelRecieve?.Cancel();
this.cancelRecieve?.Dispose();
try
{
this.client?.Close();
}
catch(ObjectDisposedException) { }
}
但是 catch
不会对 ObjectDisposedException
使用react。
最佳答案
于是,经过将近一周的煎熬,我找到了原因和解决办法。
起初,我查看了UdpClient
源代码。 ReceiveAsync
方法:
[HostProtection(ExternalThreading = true)]
public Task<UdpReceiveResult> ReceiveAsync()
{
return Task<UdpReceiveResult>.Factory.FromAsync((callback, state) => BeginReceive(callback, state), (ar)=>
{
IPEndPoint remoteEP = null;
Byte[] buffer = EndReceive(ar, ref remoteEP);
return new UdpReceiveResult(buffer, remoteEP);
}, null);
}
第二次,我发现这个帖子有完美的答案:How to abort socket's BeginReceive()? ,其中说:
To cancel a pending call to the BeginConnect() method, close the Socket. When the Close() method is called while an asynchronous operation is in progress, the callback provided to the BeginConnect() method is called. A subsequent call to the EndConnect(IAsyncResult) method will throw an ObjectDisposedException to indicate that the operation has been cancelled.
而且,正如我们所见,原始的 ReceiveAsync
方法返回给我们 ObjectDisposedException
,因为 IOOperation
在 之后还没有完成关闭
调用。
为了克服这个问题,我这样做了:
新的ReceiveAsync
实现:
/// <summary>
/// Асинхронный запрос на ожидание приёма данных с возможностью досрочного выхода
/// (для выхода из ожидания вызовите метод Disconnect())
/// </summary>
/// <param name="client">Рабочий экземпляр класса UdpClient</param>
/// <param name="breakToken">Признак досрочного завершения</param>
/// <returns>Если breakToken произошёл до вызова данного метода или в режиме ожидания
/// ответа, вернёт пустой UdpReceiveResult; при удачном получении ответа-результат
/// асинхронной операции чтения</returns>
public Task<UdpReceiveResult> ReceiveAsync(UdpClient client, CancellationToken breakToken)
=> breakToken.IsCancellationRequested
? Task<UdpReceiveResult>.Run(() => new UdpReceiveResult())
: Task<UdpReceiveResult>.Factory.FromAsync(
(callback, state) => client.BeginReceive(callback, state),
(ar) =>
{
/// Предотвращение <exception cref="ObjectDisposedException"/>
if (breakToken.IsCancellationRequested)
return new UdpReceiveResult();
IPEndPoint remoteEP = null;
var buffer = client.EndReceive(ar, ref remoteEP);
return new UdpReceiveResult(buffer, remoteEP);
},
null);
新的Dispose
实现:
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
this.cancelReceive?.Cancel();
this.client?.Close();
this.cancelReceive?.Dispose();
}
}
我非常希望,我的决定能使其他人摆脱我所经历的痛苦。
关于c# - UdpClient.ReceiveAsync 正确提前终止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41019997/
我有一个小问题和一个解决方案,但我想了解到底发生了什么。根据 UdpClient 的构造函数,我使用 EndReceive() 是否抛出套接字异常(10054 - 现有连接已被远程主机关闭(翻译自德语
从本质上讲,除了明显的区别之外,它们之间还有哪些区别?我什么时候应该使用哪种形式? class What { public Go() { Thread thread =
我正在维护其他人的代码及其使用类 UdpClient .该代码声明了 UdpClient 的一个实例并使用 UdpClient.Receive() 连续接收数据. 当接收到数据时,在另一个线程中进行处
我正在使用下面的代码,似乎有时套接字未释放 我是怎么发现的? 通过使用进程浏览器(来自sysinternal), 申请的专有权 然后进入“TCP/IP”选项卡。 通过在控制台中输入“netstat -
我正在尝试构建一个客户端服务器套接字库,它将抽象发送和接收数据的复杂性。我想知道你是否有一个 UDP 服务器设置来拥有一个多播组。如果需要,它仍然可以向特定客户端发送和接收单播请求吗?还是您必须打开两
我一直在试验 C# 中的 UDP 发送和接收,但遇到了一个奇怪的问题。该代码在控制台应用程序中运行良好,但当我尝试在服务中使用完全相同的代码时,client.Receive 方法被阻止。该服务正常运行
我们有一个从远程设备收集遥测数据的生产系统。此数据以合理的频率发送,我们最终在高峰时段每秒接收多达数千条消息。每条消息的有效负载约为 80 字节。我开始对各种存储机制进行一些性能测试,但我想首先我会尝
我是 C# UDP 编码的新手,在我的电脑上本地使用 UDP 客户端时,我有一些“奇怪”的行为。我想将 UDP 数据从我电脑上的一个端口 (11000) 发送到同一台电脑上的另一个端口 (12000)
在 c# 中,我正在使用 UdpClient.Receive 函数: public void StartUdpListener(Object state) { try
我在使用 C# 中的 UdpClient 时遇到问题。我正在两个客户端之间通过互联网流式传输音频。 在我的麦克风上,采样率为 16khz,我发送带有音频的 UDP 数据包,每个数据包 6400 字节。
在尝试处理 UdpClient 时,我发现这是不可能的。对于以下内容: UdpClient udpClient = new UdpClient(); udpClient.Dispose(); Visu
我只是在玩 UdpClient 并注意到将 UdpClient.EnableBroadcast 设置为 true 或 false 不会没有任何(副作用)效果,我可以用任何一种方式进行广播: using
我正在实现一个简单的本地网络发现协议(protocol),因此我调用了 UdpClient.Send,然后调用了 UdpClient.BeginReceive。如果有多个响应未决,我会在回调结束时调用
我正在尝试将 LAN 服务器发现添加到我的 Unity 游戏中。我正在使用 UDP 广播请求。如果网络上的任何人是服务器,他们将响应一些服务器数据。我已经弄清楚了这部分,但我需要使用一些 Unity
我正在创建一个聊天应用程序,其中用户位于路由器 (NAT) 后面。所以主要问题是向这些客户发送消息。服务器接收消息没有问题。 这是我的协议(protocol)(规则): UdpServer监听来自 c
我正在尝试运行一个基本的 UDPCLient-Server 程序。当我编译 UDPClient 程序时,会导致以下错误。虽然我的服务器编译成功。 有人可以指导出什么问题吗? 错误: UDPClient
public void send_multicast(string message) { UdpClient c = new UdpClient(10102);
我在构建指定 IPv4 系列的 UdpClient 对象时遇到异常。这只发生在一台 Windows 7 64 位机器上,其他具有相同操作系统的机器工作正常。 确切的异常(exception)是: Sy
我有一个服务于某些线程的类实例(我们称它为 A),该实例仅通过 UdpClient 类发送 UDP 数据包。它在其构造函数中初始化 UdpClient,仅用于发送数据包。 它看起来像: public
美好的一天。我使用 UdpClient 并对其进行包装。 为了阅读我有异步方法: private async Task Receive(UdpClient client, CancellationTo
我是一名优秀的程序员,十分优秀!