UnobservedTaskException 可能发生在哪里?
Where could an UnobservedTaskException be occurring?
我有一个访问 WCF 服务的 WPF 客户端。该服务使用计时器非常好地运行,每 n 分钟执行一些处理。客户端 UI 有一个 ProcessNow
命令,它会覆盖服务的计时器,并立即执行处理。我正在尝试解决一个可用性问题,即多次单击 Process Now
按钮,而处理仍然很忙,导致 "connection closed" 异常,来自我假设的 WCF 通信通道,然后是 UnobservedTaskException
。
异常消息解释说它的原因不是没有等待任务,就是没有访问它的 Exception
属性。在我的解决方案中的任何地方,我只有两个明显的 Task
用法,一个在我的视图模型中:
async void ExecuteProcessNowCommand()
{
await _proxy.ProcessAsync(true);
}
另一个是在同一视图模型中的一个小工具方法中:
private void ExecuteWithTimeout(Action task, int? timeout = null)
{
timeout = timeout ?? HostServiceConstants.ServiceControlTimeout;
var source = new CancellationTokenSource();
var timedTask = new Task(task, source.Token);
timedTask.Start();
bool done = timedTask.Wait(timeout.Value);
if (!done)
{
source.Cancel();
var frame = new StackFrame(1);
var methodName = frame.GetMethod().Name;
_logger.Warn("'{0}' timed out after {1} milliseconds.", methodName, timeout);
}
}
在第一个代码摘录中,我似乎确实在等待任务,但根据我在网上某处找到的示例,我更怀疑第二个。我用它来尝试执行非阻塞检查,例如:
bool CanExecuteProcessNowCommand()
{
bool result = false;
ExecuteWithTimeout(() =>
{
try
{
result = _proxy.CanUserForceProcessing();
}
catch (EndpointNotFoundException)
{
result = false;
}
});
return result;
}
当我尝试更新我的命令按钮时,在我的 WCF 客户端中调用了最后一段代码:
ProcessNow.RaiseCanExecuteChanged();
我对异步和 WCF 都很陌生,所以请原谅这里的任何明显错误。
ExecuteProcessNowCommand
不会造成这种情况。如果在 async void 方法中抛出未处理的异常,进程将被关闭。所以事实并非如此。
只剩下ExecuteWithTimeout
了。是的,如果在 timedTask
.
中抛出未处理的异常,它可能会导致结果 UnObservedTaskException
您正在等待,等待应该会观察到异常,但您正在等待超时。如果在超时后抛出异常,您将看到此行为。
您需要将延续附加到 timedTask
并观察异常。
我有一个访问 WCF 服务的 WPF 客户端。该服务使用计时器非常好地运行,每 n 分钟执行一些处理。客户端 UI 有一个 ProcessNow
命令,它会覆盖服务的计时器,并立即执行处理。我正在尝试解决一个可用性问题,即多次单击 Process Now
按钮,而处理仍然很忙,导致 "connection closed" 异常,来自我假设的 WCF 通信通道,然后是 UnobservedTaskException
。
异常消息解释说它的原因不是没有等待任务,就是没有访问它的 Exception
属性。在我的解决方案中的任何地方,我只有两个明显的 Task
用法,一个在我的视图模型中:
async void ExecuteProcessNowCommand()
{
await _proxy.ProcessAsync(true);
}
另一个是在同一视图模型中的一个小工具方法中:
private void ExecuteWithTimeout(Action task, int? timeout = null)
{
timeout = timeout ?? HostServiceConstants.ServiceControlTimeout;
var source = new CancellationTokenSource();
var timedTask = new Task(task, source.Token);
timedTask.Start();
bool done = timedTask.Wait(timeout.Value);
if (!done)
{
source.Cancel();
var frame = new StackFrame(1);
var methodName = frame.GetMethod().Name;
_logger.Warn("'{0}' timed out after {1} milliseconds.", methodName, timeout);
}
}
在第一个代码摘录中,我似乎确实在等待任务,但根据我在网上某处找到的示例,我更怀疑第二个。我用它来尝试执行非阻塞检查,例如:
bool CanExecuteProcessNowCommand()
{
bool result = false;
ExecuteWithTimeout(() =>
{
try
{
result = _proxy.CanUserForceProcessing();
}
catch (EndpointNotFoundException)
{
result = false;
}
});
return result;
}
当我尝试更新我的命令按钮时,在我的 WCF 客户端中调用了最后一段代码:
ProcessNow.RaiseCanExecuteChanged();
我对异步和 WCF 都很陌生,所以请原谅这里的任何明显错误。
ExecuteProcessNowCommand
不会造成这种情况。如果在 async void 方法中抛出未处理的异常,进程将被关闭。所以事实并非如此。
只剩下ExecuteWithTimeout
了。是的,如果在 timedTask
.
UnObservedTaskException
您正在等待,等待应该会观察到异常,但您正在等待超时。如果在超时后抛出异常,您将看到此行为。
您需要将延续附加到 timedTask
并观察异常。