c# - 为什么这段代码是同步运行的?

标签 c# multithreading async-await task-parallel-library task

我试图通过代码来理解并发。我有一个代码片段,我认为它是异步运行的。但是当我把debug 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;
  }

这是即时窗口中的输出:

About to call ComputeBB
Starting ComputeBB.
Compute BB took 00:00:00.1790574
Just called await ComputBB.

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

About to call ComputeBB
Just called await ComputBB.
Starting ComputeBB.
Compute BB took 00:00:00.1790574

但事实并非如此。

阐述 调用代码具有如下签名: 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;
  }

最佳答案

I have a code snippet which I thought was running asynchronously. But when I put the debug writeline statements in, I found that it is running synchronously.

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

what I need to do differently to push ComputeBB() onto another thread

它已经在线程池线程上运行。如果您不想以“即发即忘”的方式异步等待它,不要await 表达式。请注意这会对异常处理产生影响.所提供的委托(delegate)中发生的任何异常都将在给定的 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;
}

当您使用 tsk.Result 时,您当前正在做的是同步阻塞。此外,出于某种原因,您调用了 Task.Run 两次,每个方法一次。那是不必要的。如果你想从 CreateFromExistingFile 返回你的 ptsDTM 实例,你将不得不 await 它,没有绕过它。 “即发即弃”的执行根本不关心结果。它只是想开始它需要的任何操作,如果它失败或成功通常是无关紧要的。这显然不是这里的情况。

你需要做这样的事情:

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

   return returnDTM;
}

然后在调用堆栈的更高位置,您实际上不需要 CreateFromExistingFiles,只需调用:

Task.Run(() => LoadAsBinary(fileName));

需要时。

另外,请阅读 C# naming conventions ,您目前没有关注。

关于c# - 为什么这段代码是同步运行的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30022843/

相关文章:

c# - WCF 服务,我可以在浏览器中查看输出吗?

java - 列出 Android 设备上的所有一种文件类型?

c# - 使用异步方法选择

c# - 在导航之前取消等待方法的最佳方法?

java - C# Little-Endian 从 Java Big-Endian 转换

c# - 使用 EF 模型从字符串字段中存储和检索枚举的无缝方式

android - Android 设备上的并行应用程序

c# - 你在那里,异步写入值吗?

c# - 在两个项目中找不到属性的架构信息

java - 从不同的线程填充数组