我正在测试我的类librabry,它会向网络服务器发送异步帖子。 由于要发送的数据需要不同的操作,我插入方法来处理并在blockingcollection中发送它们。永久运行的任务从集合中提取每个方法并执行它。 问题是,如果帖子失败,则错误不会冒泡到wpf调用者模块。
这是图书馆模块
private Task queueInvio;
private BlockingCollection<Action> codaInvio = null;
public MotoreClient()
{
codaInvio = new BlockingCollection<Action>();
queueInvio = Task.Factory.StartNew(() =>
{
while (true)
{
Action azione = null;
if (codaInvio.TryTake(out azione))
{
try
{
azione();
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
}
, CancellationToken.None
, TaskCreationOptions.LongRunning
, TaskScheduler.Default);
}
这是wpf测试程序调用的方法
public void InviaAggiornamento(TipoAggiornamento tipoAggiornamento)
{
string nomePaginaApi = String.Empty;
HttpContent contenuto = null;
switch (tipoAggiornamento)
{
// blah blah code
}
// exception capture here, but not rethrown to the wpf module
codaInvio.Add(async () =>
{
try
{
await InviaAggiornamento(nomePaginaApi, contenuto);
}
catch (Exception ex)
{
throw;
}
});
}
这是制作异步发布的方法
private async Task InviaAggiornamento(string nomePaginaApi, HttpContent contenuto)
{
HttpClient httpClient = new HttpClient();
string riposta = String.Empty;
if (!string.IsNullOrEmpty(indirizzoServer))
{
try
{
httpClient.BaseAddress = new Uri(IndirizzoServer);
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", USERNAME, PASSWORD))));
var response = await httpClient.PostAsync("api/liveTimingApi/" + nomePaginaApi, contenuto);
if (response.StatusCode != HttpStatusCode.NoContent)
throw new Exception("Richiesta PostAsync fallita.");
if (!response.IsSuccessStatusCode)
{
string rispostaErrore = string.Empty;
if (!string.IsNullOrEmpty(response.ReasonPhrase))
rispostaErrore += " ReasonPhrase: " + response.ReasonPhrase;
if (!string.IsNullOrEmpty(response.Content.ReadAsStringAsync().Result))
rispostaErrore += " Result: " + response.Content.ReadAsStringAsync().Result;
throw new ServerException(rispostaErrore.Trim());
}
}
catch (HttpRequestException hre)
{
throw new Exception("HttpRequestException: " + hre.Message);
}
catch (TaskCanceledException)
{
throw new Exception("Richiesta cancellata (TaskCanceledException).");
}
catch (Exception ex)
{
throw new Exception("Exception: " + ex.Message);
}
finally
{
if (httpClient != null)
{
httpClient.Dispose();
httpClient = null;
}
}
}
}
这是模拟数据发送的wpf模块
private void btnSendTest_Click(object sender, RoutedEventArgs e)
{
motoreClient.IndirizzoServer = "http://localhost:721";
motoreClient.AggiungiRigaProgrammaOrario(1, 1, "GaraDescrizione", DateTime.Now, "XXX", "SessioneDescrizione", "1:00:00", true);
try
{
motoreClient.InviaAggiornamento(TipoAggiornamento.ProgrammaOrario);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
由于IndirizzoServer(服务器地址)是假的,我有一个HttpRequest异常。 我在codaInvio.Add try / catch块中捕获它,但是我无法将它重新抛出到调用者wpf模块。 Visual Studio表示调用者代码不处理异常。 为什么?我正在使用try / catch所有相关代码。
如果我不清楚请告诉我。
马
答案 0 :(得分:2)
你的核心问题在于:
BlockingCollection<Action>
Action
是void
- 返回委托类型,因此当您将async
lambda传递给Add
时,它正在创建async void
方法。有几个原因可以避免async void
;一个是使用try
/ catch
您可以将代理类型更改为与async Task
兼容,即BlockingCollection<Func<Task>>
,假设传递给Add
的所有代理均为{{1} }}。这将需要你的&#34;永远运行&#34;任务到async
结果,使其代表也await
。然后您需要从async
更改为Task.Factory.StartNew
,因为StartNew
doesn't understand async
delegates。
但实际上,我建议使用更简单的解决方案:使用TPL Dataflow中的Task.Run
(可通过NuGet获取)。