C# 保证代码在单独的线程中完成
我已经编写了以下代码,以在不同的线程中执行一个方法,将一个新的工作卸载到新的线程中,这样我的主线程就可以快速处理其余的工作,并完成网页请求C# 保证代码在单独的线程中完成,c#,asp.net,.net,multithreading,task-parallel-library,C#,Asp.net,.net,Multithreading,Task Parallel Library,我已经编写了以下代码,以在不同的线程中执行一个方法,将一个新的工作卸载到新的线程中,这样我的主线程就可以快速处理其余的工作,并完成网页请求 public static Task ExecuteAsynchronously(Action action) { HttpContext currentContext = HttpContext.Current; System.Threading.Tasks.Task task = System.Threading.Tasks.Task.F
public static Task ExecuteAsynchronously(Action action)
{
HttpContext currentContext = HttpContext.Current;
System.Threading.Tasks.Task task = System.Threading.Tasks.Task.Factory.StartNew(()
=>
{
HttpContext.Current = currentContext;
// Execute the desired action
action();
});
return task;
}
我将从页面的页面加载事件从ASP.NET Web UI上下文调用该方法:
protected void Page_Load(object sender, EventArgs e)
{
MethodA()
Utility.ExecuteAsynchronously(() =>
{
// Do a long running task in separate thread
MethodC()
});
MethodB()
}
i、 e
我对上述代码有以下问题:
方法A
和方法B
方法完成工作之前完成ASP.NET
上下文中使用Task.Factory.StartNew
吗
保证我们在单独任务中分配的工作能够完成ASP.NET
主要是服务于
请求并确保单独线程中的代码将完成
当ASP.NET
页面的请求被取消时,不会在这段时间内中止
以前完成的?这可能吗async wait
来解决这个问题吗public static Task ExecuteAsynchronously(Action action)
{
HttpContext currentContext = HttpContext.Current;
System.Threading.Tasks.Task task = System.Threading.Tasks.Task.Factory.StartNew(()
=>
{
HttpContext.Current = currentContext;
// Execute the desired action
action();
});
return task;
}
如果页面加载事件在MethodA
和MethodB
方法中完成工作之前完成,是否可以保证代码在单独的线程中执行长时间运行的任务将完成,或者可以中止
不,根本不能保证。此外,此任务的线程可能会被重新用于处理其他一些响应,而不会向您发出任何通知
我们甚至可以在ASP.NET上下文中使用Task.Factory.StartNew
,并保证我们在单独任务中分配的工作能够完成吗
如前所述,这些都不能保证。此外,StartNew
是不应该使用的内部方法,Task.Run
更可取,但在这种情况下没有帮助
我们如何才能确保从ASP.NET主要线程(为请求提供服务)中移除沉重/漫长的操作负载(在某些方法中),并确保在ASP.NET页面的请求之前完成时,单独线程中的代码将完成,并且不会在这两个线程之间中止?这可能吗
正如在评论中已经说过的,如果您不需要后台任务的结果,那么应该使用HostingEnvironment.QueueBackgroundWorkItem
方法来完成此类工作
我们可以用异步等待来解决这个问题吗
ASP.NET
根据定义已经是异步的。如果需要结果,不需要让另一个线程执行操作-只需在当前线程中运行代码即可
现在,回到你真正的问题上来。您试图做的是将HttpContext.Current
传递给后台任务,这是不推荐做的事情。发件人:
调用者的消息不会流到工作项。例如,在后台线程中运行的代码无法访问常用的上下文属性如果需要信息,请将所关心的值复制到状态对象或闭包中,并将其传递给后台工作程序。
不要传递实例本身,因为它不是线程安全的对象,甚至简单的属性获取程序(如)也可能抛出
因此,您需要将代码更改为,并从中复制值
其他相关资源:
- 菲尔·哈克
- 斯科特·汉斯曼
- “答案是@StephenCleary
Scott Hanselman撰写了一篇有用的博文,如果你阅读了我链接的博文,你就会意识到,无论背景任务的性质如何,有些解决方案都是适用的。你也会意识到你把重点放在了错误的风险上(例如,随机创建的任务或线程的最大风险是ASP.Net对它们没有真正的了解,因此可以随意回收应用程序池,这将杀死一个简单的任务)@Damien_不信者我无意冒犯你的编辑。“ASP.Net对它们没有真正的了解,因此可以随意回收应用程序池,这将杀死一个简单的任务”除了回收,如果我的请求在此之前完成,我的任务是否会被杀死?不,恰恰相反。正如我上面所说的,风险在于asp.net不了解此任务。更准确地说,没有任何东西将该任务链接到原始请求。好的,您的意思是,由于没有关于当前请求的新任务的知识,因此它可以自行完成,并且即使原始ASP.NET请求已完成,也不会死亡。感谢您分别回答每一点。您需要回答的主要问题是,操作的完成是否与请求相关,如果相关,则应等待。假设操作的完成与请求无关,它独立于请求,但我希望任务能够确保完成,即使请求在它之前已经关闭/完成。如果我们不等待,这项任务会完成吗