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