Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Parallel.ForEach和Task.Factory.StartNew中记录每个项的异常_C#_Task Parallel Library - Fatal编程技术网

C# 在Parallel.ForEach和Task.Factory.StartNew中记录每个项的异常

C# 在Parallel.ForEach和Task.Factory.StartNew中记录每个项的异常,c#,task-parallel-library,C#,Task Parallel Library,我正在尝试对列表使用Parallel.ForEach,并尝试对列表中的每个项目进行数据库调用。我正在尝试记录每个项目是否有错误。我只是想和这里的专家们确认一下我的做法是否正确。对于本例,我使用文件访问而不是数据库访问来模拟I/O static ConcurrentQueue<IdAndErrorMessage> queue = new ConcurrentQueue<IdAndErrorMessage>(); private static void Run

我正在尝试对列表使用Parallel.ForEach,并尝试对列表中的每个项目进行数据库调用。我正在尝试记录每个项目是否有错误。我只是想和这里的专家们确认一下我的做法是否正确。对于本例,我使用文件访问而不是数据库访问来模拟I/O

    static ConcurrentQueue<IdAndErrorMessage> queue = new ConcurrentQueue<IdAndErrorMessage>();
    private static void RunParallelForEach()
    {
      List<int> list = Enumerable.Range(1, 5).ToList<int>();
      Console.WriteLine("Start....");
      Stopwatch stopWatch = new Stopwatch();
      stopWatch.Start();
      Parallel.ForEach(list, (tempId) =>
      {
        string errorMessage = string.Empty;
        try
        {
          ComputeBoundOperationTest(tempId);
           try
           {
              Task[] task = new Task[1]
              {
               Task.Factory.StartNew(() =>  this.contentFactory.ContentFileUpdate(content, fileId))
              };
           }
           catch (Exception ex)
           {
              this.tableContentFileConversionInfoQueue.Enqueue(new ContentFileConversionInfo(fileId, ex.ToString()));
           }
        }
        catch (Exception ex)
        {
          errorMessage = ex.ToString();
        }
        if (queue.SingleOrDefault((IdAndErrorMessageObj) => IdAndErrorMessageObj.Id == tempId) == null)
        {
            queue.Enqueue(new IdAndErrorMessage(tempId, errorMessage));
        }
     }
     );
     Console.WriteLine("Stop....");
     Console.WriteLine("Total milliseconds :- " + stopWatch.ElapsedMilliseconds.ToString());
}
静态ConcurrentQueue队列=新建ConcurrentQueue();
私有静态void RunParallelForEach()
{
List=Enumerable.Range(1,5).ToList();
Console.WriteLine(“开始…”);
秒表秒表=新秒表();
秒表。开始();
Parallel.ForEach(list,(tempId)=>
{
string errorMessage=string.Empty;
尝试
{
计算边界操作测试(tempId);
尝试
{
任务[]任务=新任务[1]
{
Task.Factory.StartNew(()=>this.contentFactory.ContentFileUpdate(content,fileId))
};
}
捕获(例外情况除外)
{
这个.tableContentFileConversionInfo.Enqueue(新的ContentFileConversionInfo(fileId,例如.ToString());
}
}
捕获(例外情况除外)
{
errorMessage=ex.ToString();
}
if(queue.SingleOrDefault((IdAndErrorMessageObj)=>IdAndErrorMessageObj.Id==tempId)==null)
{
排队(新的IdAndErrorMessage(tempId,errorMessage));
}
}
);
控制台。写入线(“停止…”);
WriteLine(“总毫秒:-”+stopWatch.elapsedmillesons.ToString());
}
以下是帮助器方法:-

private static byte[] FileAccess(int id)
{
    if (id == 5)
    {
      throw new ApplicationException("This is some file access exception");
    }
     return File.ReadAllBytes(Directory.GetFiles(Environment.SystemDirectory).First());
            //return File.ReadAllBytes("Files/" + fileName + ".docx");
}

 private static void ComputeBoundOperationTest(int tempId)
 {
    //Console.WriteLine("Compute-bound operation started for :- " + tempId.ToString());
    if (tempId == 4)
    {
       throw new ApplicationException("Error thrown for id = 4 from compute-bound operation");
    }
    Thread.Sleep(20);
 }

 private static void EnumerateQueue(ConcurrentQueue<IdAndErrorMessage> queue)
 {
    Console.WriteLine("Enumerating the queue items :- ");
    foreach (var item in queue)
    {
      Console.WriteLine(item.Id.ToString() + (!string.IsNullOrWhiteSpace(item.ErrorMessage) ? item.ErrorMessage : "No error"));
    }
 }
私有静态字节[]文件访问(int-id)
{
如果(id==5)
{
抛出新的ApplicationException(“这是一些文件访问异常”);
}
返回File.ReadAllBytes(Directory.GetFiles(Environment.SystemDirectory.First());
//返回File.ReadAllBytes(“Files/”+fileName+“.docx”);
}
专用静态void ComputeBoundOperationTest(int tempId)
{
//WriteLine(“为:-“+tempId.ToString()启动了计算绑定操作”);
if(tempId==4)
{
抛出新的ApplicationException(“从计算绑定操作中为id=4抛出错误”);
}
睡眠(20);
}
专用静态队列(ConcurrentQueue队列)
{
WriteLine(“枚举队列项:-”);
foreach(队列中的变量项)
{
Console.WriteLine(item.Id.ToString()+(!string.IsNullOrWhiteSpace(item.ErrorMessage)?item.ErrorMessage:“无错误”);
}
}

没有理由这样做:

/*Below task is I/O bound - so do this Async.*/
Task[] task = new Task[1]
{
    Task.Factory.StartNew(() => FileAccess(tempId))
};
Task.WaitAll(task);
通过将其安排在单独的任务中,然后立即等待,您只需要占用更多线程。您最好将此作为:

/*Below task is I/O bound - but just call it.*/
FileAccess(tempId);

所说的,考虑到每个项目都在记录日志值(异常或成功),您可能需要考虑将此写入一个方法,然后将整个事件调用为PLIQ查询。

例如,如果将其写入处理try/catch(无线程)的方法,并返回“记录的字符串”,即:

您可以将整个操作编写为:

var results = theIDs.AsParallel().Select(id => ProcessItem(id));

Parallel.ForEach
并发运行操作/func,最多可同时运行一定数量的实例。如果这些迭代中的每一个所做的不是本质上相互独立的,那么您就不会获得任何性能提升。而且,可能会通过引入昂贵的上下文切换和争用来降低性能。你说你想做一个“数据库调用”,并用一个文件操作来模拟它。如果每次迭代都使用相同的资源(例如,数据库表中的同一行;或者尝试写入同一位置的同一文件),那么它们实际上不会并行运行。一次只运行一个,其他的将只是“等待”获取资源——不必要地使代码复杂化


您还没有详细说明每个迭代要做什么;但是当我在其他程序员身上遇到这种情况时,他们几乎总是不是真正并行地做事情,他们只是简单地用
parallel.foreach
替换
foreach
,希望神奇地获得性能或神奇地利用多CPU/核心处理器。

您可能想从线程代码中删除
控制台.WriteLine
。原因是每个windows应用程序只能有一个控制台。所以,若两个或多个线程将并行写入控制台,那个么其中一个线程必须等待

作为自定义错误队列的替代,您可能希望看到并捕获该错误队列,并相应地处理异常。
InnerExceptions
属性将为您提供必要的异常列表。更多


还有一个一般的代码评论,不要在
if(tempId==4)
中使用像
4
这样的幻数,而是定义一些常量,告诉4代表什么。e、 g.
if(tempId==Error.FileMissing)

对Thread.Sleep()的调用是怎么回事?这“神奇地”让它工作了吗?除了实际的答案,这个代码有点混乱。魔法数字4怎么了?为什么要尝试嵌套块?为什么要忽略所有异常?…@Ankush-这个数字只是为了模拟我们可能会在某个项目上遇到异常。@Peter-Thread.Sleep()是为了模拟一些计算绑定的工作。让我备份一下-我执行“Task.WaitAll”的唯一原因是为了在FileAccess方法期间捕获任何异常(如果有)。有更好的异常处理方法吗?@AshishGupta您可以使用
task.Wait()
-但是如果您按照我的建议序列化ti,您不必这样做-异常将直接在该线程中引发请查看我更新的问题。在每次迭代中,我都尝试执行一个计算绑定任务和一个数据库调用(此处为I/O模拟的文件访问)任务。我一直认为通过异步进行I/O总是比使用异步方式更好
var results = theIDs.AsParallel().Select(id => ProcessItem(id));