【发布时间】:2017-02-07 13:35:29
【问题描述】:
我已经实现了一个服务名称ExamClient,它有两个操作,一个是Ping,它返回一个基本的string,这意味着服务可用,一个是FindStudy,它在数据库中搜索可能需要很长时间继续。
在另一边,我有几个ExamClient 端点,我想按任务每个端点运行FindStudy,所以在Dispatcher 中我有这样的东西:
public FindStudies_DTO_OUT FindStudies(FindStudies_DTO_IN findStudies_DTO_IN)
{
List<Study_C> ret = new List<Study_C>();
List<Task> tasks = new List<Task>();
foreach (var sp in Cluster)
{
string serviceAddress = sp.GetLibraryAddress(ServiceLibrary_C.PCM) + "/Exam.svc";
var task = Task.Run(() =>
{
ExamClient examClient = new ExamClient(serviceAddress.GetBinding(), new EndpointAddress(serviceAddress), Token);
var ping = Task.Run(() =>
{
examClient.Ping();
});
if (!ping.Wait(examClient.Endpoint.Binding.OpenTimeout))
{
Logging.Log(LoggingMode.Warning, "Timeout on FindStudies for:{0}, address:{1}", sp.Name, serviceAddress);
return new List<Study_C>(); // if return null then need to manage it on ret.AddRange(t.Result);
}
return (examClient.FindStudies(findStudies_DTO_IN).Studies.Select(x =>
{
x.StudyInstanceUID = string.Format("{0}|{1}", sp.Name, x.StudyInstanceUID);
x.InstitutionName = sp.Name;
return x;
}));
});
task.ContinueWith(t =>
{
lock (ret)
{
ret.AddRange(t.Result);
}
}, TaskContinuationOptions.OnlyOnRanToCompletion);
task.ContinueWith(t =>
{
Logging.Log(LoggingMode.Error, "FindStudies failed for :{0}, address:{1}, EXP:{2}", sp.Name, serviceAddress, t.Exception.ToString());
}, TaskContinuationOptions.OnlyOnFaulted);
tasks.Add(task);
}
try
{
Task.WaitAll(tasks.ToArray());
}
catch (AggregateException aggEx)
{
foreach (Exception exp in aggEx.InnerExceptions)
{
Logging.Log(LoggingMode.Error, "Error while FindStudies EXP:{0}", exp.ToString());
}
}
return new FindStudies_DTO_OUT(ret.Sort(findStudies_DTO_IN.SortColumnName, findStudies_DTO_IN.SortOrderBy));
}
首先我必须对每个端点运行Ping 才能知道连接已建立
之后FindStudy.
如果Cluster 中有 3 个结束点,则 6 个任务以并行模式运行,Ping 为 3 个,FindStudy 为 3 个。
我认为我处理异常的代码有问题... 那么实现这个场景的最佳方法是什么?
提前致谢。
【问题讨论】:
-
你不应该在你的任务中使用
Wait()来访问超时逻辑......查看答案here -
查看 cmets 以及有关取消令牌的内容。这真的很重要!
-
我想我应该等待,因为如果端点可用,则打开超时为 3 秒
Ping在 3 秒内得到响应。 -
不,使用
Wait()是非常糟糕的做法,可能会导致死锁。取消任务的正确方法是通过取消令牌,它们也有超时。Ping()可以接受取消令牌作为参数。 -
我认为你误会了我。您可以设置 3 秒的超时时间,但您的实现存在缺陷。
标签: c# multithreading task-parallel-library