【发布时间】:2021-12-02 15:42:45
【问题描述】:
这是我用来 ping IP 地址列表的代码。它工作正常,除了今天我收到了一个致命的未处理异常! - System.ObjectDisposedException
private static CancellationTokenSource cts = new CancellationTokenSource();
private static CancellationToken ct;
// Source per cancellation Token
ct = cts.Token;
IsRun = true;
try
{
LoopAndCheckPingAsync(AddressList.Select(a => a.IP).ToList()).ContinueWith((t) =>
{
if (t.IsFaulted)
{
Exception ex = t.Exception;
while (ex is AggregateException && ex.InnerException != null)
ex = ex.InnerException;
Global.LOG.Log("Sonar.Start() - ContinueWith Faulted:" + ex.Message);
}
else
{
// Cancellation tokek
if (cts != null)
{
cts.Dispose();
}
}
});
}
catch (Exception ex)
{
Global.LOG.Log("Sonar.Start() - Exc:" + ex.Message);
}
由于我无法复制错误,我的怀疑与 CancellationTokenSource 的 Disponse 方法有关。有什么想法可以正确处理 CancellationTokenSource?
我获取了事件查看器详细信息条目:
Informazioni sull'eccezione: System.ObjectDisposedException
in System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean ByRef)
in System.StubHelpers.StubHelpers.SafeHandleAddRef(System.Runtime.InteropServices.SafeHandle, Boolean ByRef)
in Microsoft.Win32.Win32Native.SetEvent(Microsoft.Win32.SafeHandles.SafeWaitHandle)
in System.Threading.EventWaitHandle.Set()
in System.Net.NetworkInformation.Ping.set_InAsyncCall(Boolean)
in System.Net.NetworkInformation.Ping.Finish(Boolean)
in System.Net.NetworkInformation.Ping.PingCallback(System.Object, Boolean)
in System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context(System.Object, Boolean)
in System.Threading._ThreadPoolWaitOrTimerCallback.WaitOrTimerCallback_Context_f(System.Object)
in System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
in System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
in System.Threading._ThreadPoolWaitOrTimerCallback.PerformWaitOrTimerCallback(System.Object, Boolean)
【问题讨论】:
-
你的代码看起来也坏了。如果 LoopAndCheckPingAsync 返回一个任务(方法名称暗示了这一点),你必须等待这个方法:
await LoopAndCheckPingAsync()。不要使用 Task.ContinueWith。由于您正在等待该方法,因此等待后面的代码将自动视为继续。 -
您还必须在记录其消息后抛出原始异常。
-
@BionicCode 好的,我明白了。我使用
await更改了 LoopAndCheckPingAsync 方法,但我不知道如何处理 cancelToken -
如果这是真实/完整的代码,您也必须删除完整的延续。 await 将正确处理异常,现有的 catch 将记录它们。继续是完全多余的。然后像我在回答中建议的那样控制 CancellationTokenSource 。我想知道您为什么不将 CancellationToken 传递给 LoopAndCheckPingAsync 方法?它应该有一个 CancellationToken 参数而不是一个静态引用。
-
不错的方法,我会尝试的。非常感谢@BionicCode
标签: c# cancellationtokensource