我有两个异步方法,我在窗体窗口的后台运行作为单独的线程/任务。这些是无限循环,只在后台执行一些工作,然后使用调度程序更新UI。见下文。
// Class variables
private String token_resource = "/yourApp/oauth/token?username=";
private String endpoint_rest="https://your.app.domain.com/";
private String acessToken;
@When("^user gets access token using userId \"(.+)\" and password \"(.+)\"$")
public void getAccessToken(String userName, String password){
RequestSpecification requestSpec = RestAssured.with();
requestSpec.given().contentType("application/json");
requestSpec.headers("Authorization", "Basic your-string-here");
Response response = requestSpec.post(endpoint_rest + token_resource + userName + "&password=" + password + "&client_id=yourApp&grant_type=password");
String responseMsg = response.asString();
System.out.println(">> responseMsg=" + responseMsg);
assertTrue("Missing access token",responseMsg.contains("access_token"));
System.out.println(">> Get Access token RESPONSE: " + responseMsg);
DocumentContext doc = JsonPath.parse(responseMsg);
acessToken= doc.read("access_token");
System.out.println(" >> doc.read access_token= " + acessToken);
}
这些任务是通过单击按钮启动的(代码如下所示)。我正在尝试使用等待Task.WhenAll来等待两个任务。设置取消令牌时,它按预期工作,并捕获OperationCanceledException。但是,相机或Arduino问题引发的任何异常(通过在运行期间简单地拔出USB进行模拟)似乎都没有被捕获。
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"));
}
}
}
奇怪的是,我看到输出窗口中抛出的异常,但它们没有冒泡到我的try / catch。此外,如果我只是等待一个任务,它按预期工作,异常冒泡。
任何人都知道我做错了什么?
谢谢!
答案 0 :(得分:4)
这一行
await Task.WhenAll(task1, task2);
将抛出AggregateException,如果它发生在task1和/或task2中,并且将包含来自内部所有任务的异常。
但是要发生这种情况(即你接收AggregateException)所有任务应该完成执行。
因此,在当前状态下,当两个任务中出现异常时(迟早),您将收到异常 。
如果您 需要在其中一项失败时停止所有其他任务,您可以尝试使用例如Task.WhenAny
而不是Task.WhenAll
。
另一种选择是实现一些手动同步 - 例如,引入共享标志,例如" wasAnyExceptions",每当任务中发生异常时将其设置在每个任务中,并在任务循环内检查它以停止循环执行。
根据评论更新
为了澄清,Task.WhenAll(..)
将返回任务。完成此任务后,它将包含AggregateException
,其Exception
属性中的所有失败任务都有例外。
如果您await
执行此类任务,它将从列表中的第一个故障任务中抛出未解包的异常。
如果您.Wait()
执行此任务,您将收到AggregateException
。