【发布时间】:2016-06-21 19:45:11
【问题描述】:
我在开发一些 ASP.Net 应用程序时看到一些空引用问题。例外情况如下:
Description: The process was terminated due to an unhandled exception.
Exception Info: System.NullReferenceException
Stack:
at System.Threading.Tasks.AwaitTaskContinuation.<ThrowAsyncIfNecessary>b__1(System.Object)
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
通过谷歌和SO搜索后,很可能是我的一些代码以这种方式触发并忘记了异步任务:
public interface IRepeatedTaskRunner
{
Task Start();
void Pause();
}
public class RepeatedTaskRunner : IRepeatedTaskRunner
{
public async Task Start() //this is returning Task
{
...
}
}
public class RepeatedTaskRunnerManager{
private IRepeatedTaskRunner _runner;
public void Foo(){
_runner.Start(); //this is not awaited.
}
}
我认为这与这个问题"Fire and forget async method in asp.net mvc" 非常相似,但并不完全相同,因为我的代码不在控制器上并接受请求。我的代码专门用于运行后台任务。
与上面的 SO 问题一样,通过将代码更改为下面的代码来解决问题,但我只想知道为什么以及从 Task.Run 返回的任务和触发和忘记异步任务有什么区别:
public interface IRepeatedTaskRunner
{
Task Start();
void Pause();
}
public class RepeatedTaskRunner : IRepeatedTaskRunner
{
public Task Start() // async is removed.
{
...
}
}
public class RepeatedTaskRunnerManager{
private IRepeatedTaskRunner _runner;
public void Foo(){
Task.Run(() => _runner.Start()); //this is not waited.
}
}
从我的角度来看,这两个代码都只是创建了一个任务而忘记了它。唯一的区别是第一个任务没有等待。这会导致行为上的差异吗?
从另一个 SO 问题中,我知道火灾和遗忘模式的局限性和不良影响。
标签: c# asp.net multithreading asynchronous async-await