我有兩個異步方法,我在表單窗口的背景下作爲單獨的線程/任務運行。這些是無限循環,只是在後臺執行一些工作,然後使用調度程序更新UI。見下文。Task.WhenAll沒有按預期拋出異常
public async Task RunCameraThread(CancellationToken cancelToken)
{
while (true)
{
// If cancellation token is set, get out of the thread & throw a cancel exception
cancelToken.ThrowIfCancellationRequested();
// Get an image from the camera
CameraBitmap = Camera.CaptureImage(true);
// Update the UI (use lock to prevent simultaneous use of Dispatcher object in other thread)
lock (Dispatcher)
{
Dispatcher.Invoke(() => pictureBoxCamera.Image = tempBitmap);
Dispatcher.Invoke(() => pictureBoxCamera.Invalidate());
}
}
}
public async Task RunDistanceSensorThread(CancellationToken cancelToken)
{
while (true)
{
// If cancellation token is set, get out of the thread & throw a cancel exception
cancelToken.ThrowIfCancellationRequested();
// Get the distance value from the distance sensor
float distance = Arduino.AverageDistance(10, 100);
// Update the UI (use lock to prevent simultaneous use of Dispatcher object)
lock (Dispatcher)
{
Dispatcher.Invoke(() => textBoxDistanceSensor.Text = distance.ToString("0.00"));
}
}
}
這些任務是通過單擊按鈕(代碼如下)啓動的。我試圖使用等待Task.WhenAll爲了等待這兩個任務。當設置取消標記時,它將按預期工作,並捕獲OperationCanceledException。但是,由Camera或Arduino問題引發的任何異常(在運行期間通過拔下USB來模擬)似乎都沒有被捕獲。
private async void buttonConnect_Click(object sender, EventArgs e)
{
try
{
// Disable UI so we cannot click other buttons
DisableComponentsUI();
// Connect to Nimbus, Camera and Arduino
await Task.Run(() => Nimbus.ConnectAsync());
Camera.Connect();
Camera.ManagedCam.StartCapture();
Arduino.Connect();
// Get the current Nimbus positions and enable UI
UpdatePositionsUI();
EnableComponentsUI();
// Reset cancel token and start the background threads and await on them (this allows exceptions to bubble up to this try/catch statement)
StopTokenSource = new CancellationTokenSource();
var task1 = Task.Run(() => RunCameraThread(StopTokenSource.Token));
var task2 = Task.Run(() => RunDistanceSensorThread(StopTokenSource.Token));
await Task.WhenAll(task1, task2);
}
catch (OperationCanceledException exceptionMsg)
{
// Nothing needed here...
}
catch (Hamilton.Components.TransportLayer.ObjectInterfaceCommunication.ComLinkException exceptionMsg)
{
NimbusExceptionHandler(exceptionMsg);
}
catch (FlyCapture2Managed.FC2Exception exceptionMsg)
{
CameraExceptionHandler(exceptionMsg);
}
catch (IOException exceptionMsg)
{
ArduinoExceptionHandler(exceptionMsg);
}
catch (UnauthorizedAccessException exceptionMsg)
{
ArduinoExceptionHandler(exceptionMsg);
}
catch (TimeoutException exceptionMsg)
{
ArduinoExceptionHandler(exceptionMsg);
}
}
奇怪的是,我看到在輸出窗口中拋出異常,但他們不會冒泡到我的try/catch。另外,如果我只是在等待一項任務,它按預期工作,異常冒泡。
任何人有任何想法我做錯了什麼?
謝謝!
@StenPetrov是的,我期待着。它似乎會拋出一個異常,因爲我可以在輸出窗口中看到它,但是它在使用時不會冒泡到我的try/catch中。WhenAll – leonhart88
@StenPetrov'WhenAll'會拋出一個包含異常形式的'AggregateException',形成每個發生故障的任務的每一個異常,而不僅僅是第一個異常。 – Servy
@servy你確定嗎?我想你必須在'WhenAll'任務上調用'Wait',如果你想捕獲單個任務拋出的異常,如[這裏]所示(https://msdn.microsoft.com/en-us/library/hh194874( v = vs.110)的.aspx)。但是,我不知道與「等待WhenAll」任務的關係。 – Quantic