为什么这段代码同步运行?

phi*_*gon 8 c# multithreading task task-parallel-library async-await

我试图通过在代码中执行它来理解并发性.我有一个代码片段,我认为它是异步运行的.但是当我把调试writeline语句放入其中时,我发现它正在同步运行.有人可以解释我需要做什么不同的使用Task.Something将ComputeBB()推送到另一个线程?

澄清 我想让这段代码在其他一些线程中运行ComputeBB,这样主线程就会继续运行而不会阻塞.

这是代码:

{
    // part of the calling method
     Debug.WriteLine("About to call ComputeBB");
     returnDTM.myBoundingBox = await Task.Run(() => returnDTM.ComputeBB());
     Debug.WriteLine("Just called await ComputBB.");
     return returnDTM;
}

  private ptsBoundingBox2d ComputeBB()
  {
     Debug.WriteLine("Starting ComputeBB.");
     Stopwatch sw = new Stopwatch(); sw.Start();
     var point1 = this.allPoints.FirstOrDefault().Value;
     var returnBB = new ptsBoundingBox2d(
        point1.x, point1.y, point1.z, point1.x, point1.y, point1.z);
     Parallel.ForEach(this.allPoints,
        p => returnBB.expandByPoint(p.Value.x, p.Value.y, p.Value.z)
        );
     sw.Stop();
     Debug.WriteLine(String.Format("Compute BB took {0}", sw.Elapsed));
     return returnBB;
  }
Run Code Online (Sandbox Code Playgroud)

以下是即时窗口中的输出:

About to call ComputeBB
Starting ComputeBB.
Compute BB took 00:00:00.1790574
Just called await ComputBB.
Run Code Online (Sandbox Code Playgroud)

澄清 如果它真的是异步运行,它将按此顺序:

About to call ComputeBB
Just called await ComputBB.
Starting ComputeBB.
Compute BB took 00:00:00.1790574
Run Code Online (Sandbox Code Playgroud)

但事实并非如此.

详细 说明调用代码具有如下签名:private static async Task loadAsBinaryAsync(string fileName)但是,在下一级别,我尝试停止使用异步.所以这里是从上到下的调用堆栈:

  static void Main(string[] args)
  {
      aTinFile = ptsDTM.CreateFromExistingFile("TestSave.ptsTin");
      // more stuff
  }

  public static ptsDTM CreateFromExistingFile(string fileName)
  {
     ptsDTM returnTin = new ptsDTM();
     Task<ptsDTM> tsk = Task.Run(() => loadAsBinaryAsync(fileName));
     returnTin = tsk.Result;  // I suspect the problem is here.
     return retunTin;
  }

  private static async Task<ptsDTM> loadAsBinaryAsync(string fileName)
  {
      // do a lot of processing
     Debug.WriteLine("About to call ComputeBB");
     returnDTM.myBoundingBox = await Task.Run(() => returnDTM.ComputeBB());
     Debug.WriteLine("Just called await ComputBB.");
     return returnDTM;
  }
Run Code Online (Sandbox Code Playgroud)

Yuv*_*kov 8

我有一个代码片段,我认为它是异步运行的.但是当我把调试writeline语句放入其中时,我发现它正在同步运行.

await用于异步等待操作完成.这样做时,它会将控制权交还给调用方法,直到完成为止.

我需要以不同的方式将ComputeBB()推送到另一个线程

它已经在线程池线程上运行.如果你不想以"一劳永逸"的方式异步地等待它,那就不要await表达了.请注意,这将对异常处理产生影响.在提供的委托中发生的任何异常都将在给定的内部捕获Task,如果不这样await,则有可能它们将进行未处理.

编辑:

让我们看看这段代码:

public static ptsDTM CreateFromExistingFile(string fileName)
{
   ptsDTM returnTin = new ptsDTM();
   Task<ptsDTM> tsk = Task.Run(() => loadAsBinaryAsync(fileName));
   returnTin = tsk.Result;  // I suspect the problem is here.
   return retunTin;
}
Run Code Online (Sandbox Code Playgroud)

您当前正在做的是在使用时同步阻止tsk.Result.此外,由于某种原因,你Task.Run在每种方法中都会调用两次.这是不必要的.如果你想从中返回你的ptsDTM实例CreateFromExistingFile,你将不得不这样await做,没有解决这个问题."火和忘记"执行根本不关心结果.它只是想要启动它需要的任何操作,如果它失败或成功通常是不关心的.这显然不是这种情况.

你需要做这样的事情:

private PtsDtm LoadAsBinary(string fileName)
{
   Debug.WriteLine("About to call ComputeBB");
   returnDTM.myBoundingBox = returnDTM.ComputeBB();
   Debug.WriteLine("Just called ComputeBB.");

   return returnDTM;
}
Run Code Online (Sandbox Code Playgroud)

然后在调用堆栈的某个地方,你实际上并不需要CreateFromExistingFiles,只需调用:

Task.Run(() => LoadAsBinary(fileName));
Run Code Online (Sandbox Code Playgroud)

需要的时候.

另外,请阅读您目前没有关注的C#命名约定.