在C#中使用单个语句异步的最简单方法是什么?

时间:2009-08-03 17:29:39

标签: c# .net asp.net asynchronous

我在ASP.NET页面上运行了一个语句,这需要很长时间(很长一段时间我的意思是100毫秒,如果我希望这个页面闪电般快,那就太长了),我不在乎只要执行它就会执行。

实现这一目标的最佳(也是最简单)方法是什么?

8 个答案:

答案 0 :(得分:8)

最简单的方法可能是让它在线程池中执行。例如,要使这个异步:

使用System; 使用System.Threading;

class Test
{
    static void ExecuteLongRunningTask()
    {
        Console.WriteLine("Sleeping...");
        Thread.Sleep(1000);
        Console.WriteLine("... done");
    }

    static void Main()
    {
        ExecuteLongRunningTask();
        Console.WriteLine("Finished");
        Console.ReadLine();
    }
}

Main的第一行更改为:

ThreadPool.QueueUserWorkItem(x => ExecuteLongRunningTask());

请注意,如果您传入任何参数,它们将被捕获变量 - 在某些情况下可能会产生微妙的副作用(特别是如果您在循环中使用它)。

答案 1 :(得分:3)

如果是100毫秒,那就不要打扰了。您的用户无法检测到100毫秒的延迟。


编辑:一些解释。

如果我没记错的话,100毫秒(1/10秒)接近人类可以感知的最短时间。因此,为了讨论的目的,让我承认OP的网站用户可以感知到这100毫秒,并且值得将性能提高100毫秒。我从一开始就认为OP已经正确地将这个“长期运行”任务确定为100ms改进的潜在来源。那么,为什么我建议他忽略它?

正确处理多个线程并不容易,并且是难以追踪的错误源。为问题添加线程通常不是解决方案,而是您不能立即找到的其他问题的来源(*)。

我有机会一次学习这个困难的方法,一个只能在当时最快的8-cpu系统上重现的bug,然后只是通过无情地敲击这个东西,同时模拟一定程度的网络故障会导致网络管理员排队和拍摄,如果它发生在现实生活中。该错误最终是在Unix OS内核中处理信号,并且是一些指令的安排问题。

当然,我从未见过那么糟糕的事情,我仍然看到许多开发人员因多线程错误而被绊倒。这个问题似乎一方面要求通过线程“简单的出路”,另一方面,好处只有100毫秒。由于OP似乎没有经过良好测试的线程基础设施,在我看来忽略100毫秒更好,或者可能以其他方式提升性能。


(*)当然,在许多情况下,算法可以有利地并行执行并由在多个核上运行的多个线程执行。但这听起来并不像OP有这样的情况。

答案 2 :(得分:1)

在.NET应用程序的后台处理信息时,有一个后台工作线程非常有用。更多的背景将有助于更好地回答这个问题。

答案 3 :(得分:1)


// This is the delegate to use to execute the process asynchronously
public delegate void ExecuteBackgroundDelegate();

//
[STAThread]
static void Main(string[] args)
{               
    MyProcess proc = new MyProcess();

    // create an instance of our execution delegate
    ExecuteBackgroundDelegate asynchExec = new ExecuteBackgroundDelegate(proc.Execute);

    // execute this asynchronously
    asynchExec.BeginInvoke(null, null);
}

答案 4 :(得分:0)

如果您想在运行命令之前发送响应,则可以使用ThreadPool.QueueUserWorkItem在另一个线程上运行它而不会阻止您的请求。

答案 5 :(得分:0)

你可以使用ThreadPool。

ThreadPool.QueueUserWorkItem( o => Thread.Sleep(1000) /*your long task*/  );

答案 6 :(得分:0)

class Test
{
    void LongRunningTask()
    {
        Console.WriteLine("Sleeping...");
        Thread.Sleep(10000);
        Console.WriteLine("... done");
    }

    static void Main()
    {
        Test t = new Test();
        new Action(() => t.LongRunningTask()).BeginInvoke(null, t);
    }
}

答案 7 :(得分:0)

对于延迟100ms的任何线程,我都不会费心。这样做会很好:

protected void Page_Unload(object sender, EventArgs e)
{
    HttpContext.Current.Response.Flush();
    HttpContext.Current.Response.Close();

    // Your code here
}

(复制自我之前的this question答案)

由于与客户端下载页面的连接将被关闭,因此他们的浏览器将停止显示加载消息。但是,您的代码将继续正常执行。