【问题标题】:Set Timeout on Parallel.Foreach loop在 Parallel.Foreach 循环上设置超时
【发布时间】:2013-09-21 18:02:41
【问题描述】:

我必须从我的 WCF 服务向客户端发送我的自定义对象 ("Dial") 的 List。此对象有 5 个属性:Id、Name、Type、Individual_avg、Dept_avg . Id、Name 和 Type 的值来自表,但 Individual_avg 和 dept_avg 来自第 3 方服务。要求是:

  1. 从表中加载静态属性 - Id、Name、Type
  2. 在 WCF 服务中调用一个方法,该方法从 3rd 方服务获取其他 2 个属性值。

我必须在 30 秒后超时对 3rd 方服务的调用。也就是说,如果服务需要超过 30 秒的时间来响应,我必须发送仅具有从表中获取的 3 个属性的对象(Id,Name ,Type) 并将其他 2 个属性设置为 null。例如,List 中有 5 个Dials。生成 5 个线程以调用 3rd 方服务以获取 2 个属性。如果在获取 2 个 Dials 的值后发生超时,则发送 List 并为这 2 个 Dials 设置所有属性,并且只有 Id、Name 和为其他 3 个表盘设置类型。我有以下代码来实现它。

public DialResponse GetDials(DialRequest req)
{
    DialResponse response = new DialResponse();
    var indiDials = new List<DialDetails>();
    foreach (var c in indiDialIdToShow)
    {
        var indiObj = _repository.FindQueryable<DashboardDial_Tbl>().Where(p => p.DialId == c.DialIdToShow && p.IsActive == true).Select(p => new DialDetails()
            {
                Id = p.DialId,
                Name = p.DialName,
                Type = p.DialType,
             }).SingleOrDefault();
        indiDials.Add(indiObj);
    }
var timeout = 30000; // 30 seconds
var cts = new CancellationTokenSource();
var token = new CancellationToken();
token = cts.Token;
var myOptions = new ParallelOptions { CancellationToken = cts.Token };
using (var t = new Timer(_ => cts.Cancel(), null, timeout, -1))
{
    Parallel.ForEach(indiDials, myOptions, c =>
    {
        DialDetails newDial = c;
        ReadConfig(c.Id, userName, ref newDial);
        //send a reference to the "dial" object and set the 2 properties on the object

     });
 }
response.DialsList = indiDials;
}

private void ReadConfig(string userName,ref DialDetails dialObj)
{
   //call the 3rd party service
   dialObj.Individual_avg = serviceResponse.someValue;
   dialObj.dept_avg = serviceResponse.anotherValue;
}

为了测试“超时”功能,我在 "ReadConfig" 方法中放置了一个 Thread.Sleep(40000)。这将返回一个空的“拨号”列表,而不是发送只有 3 个属性(ID、名称、类型)的“拨号”放。我应该进行哪些更改才能使这段代码按预期工作?

【问题讨论】:

    标签: c# .net timeout parallel.foreach


    【解决方案1】:

    ReadConfig 正在本地执行修改,因此indiDials 不会更新。您可以将其转换为函数以返回修改后的项目。示例代码:

    private DialDetails ReadConfig(string userName,ref DialDetails dialObj)
    {
       //call the 3rd party service
       dialObj.Individual_avg = serviceResponse.someValue;
       dialObj.dept_avg = serviceResponse.anotherValue;
    
       retun dialObj;
    }
    

    并从循环中调用它,以便修改 List

    indiDials[indiDials.IndexOf(newDial)] = ReadConfig(userName, ref newDial);
    

    【讨论】:

    • 谢谢!这行得通。但是,问题是,一旦达到 30 秒的超时时间,它就不会返回任何对象。“如果服务的响应时间超过 30 秒,我必须发送仅具有从表中获取的 3 个属性的对象( Id,Name,Type) 并将其他 2 个属性设置为 null。”目前,它正在发送一个空的List,尽管已经在 Dials 上设置了 Id、Name 和 Type。
    • @user1550951 您已经在循环中设置了超时,因此它将在下一次迭代中应用(以防连接花费太长时间)。您还必须在连接本身中设置超时 (serviceResponse)。
    • @user1550951 我不知道您使用的连接类型。但是,如果您不“超时”,它将根据需要尝试,其余代码(包括您自己的超时位)将等待。您必须在设置连接时就如何处理这个问题进行一些研究/询问(一个新问题)。 timeout 属性是任何类型连接的基本配置的一部分(因此应该很容易找到它)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-01
    • 2016-01-16
    • 1970-01-01
    • 2017-08-06
    • 2012-11-18
    • 1970-01-01
    相关资源
    最近更新 更多