通过运行一个ASP.NET网页请求触发的异步操作 [英] Running an asynchronous operation triggered by an ASP.NET web page request

查看:107
本文介绍了通过运行一个ASP.NET网页请求触发的异步操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个异步操作,对于各种原因需要使用HTTP调用一个ASP.NET网页被触发。当请求我的网页,它应该开始该操作,并立即返回确认给客户端。

这方法也通过一个WCF Web服务暴露出来,它完美的作品。

在我的第一次尝试,抛出了一个异常,告诉我:

异步操作在此上下文中允许的。
页开始异步操作必须具有异步
属性设置为true,异步操作只能是
开始之前,preRenderComplete活动的网页上。

所以我当然添加了异步=真正的参数设置为 @Page 指令。现在,我没有收到错误消息,但页面被阻塞,直到异步操作完成。

我如何获得真正的发射后不管页的工作?

编辑:有些code以获得更多信息。这是比这更复杂一点,但我试图让一般的想法在里面。

 公共部分类SendMessagePage:System.Web.UI.Page
{
    保护无效的Page_Load(对象发件人,EventArgs的发送)
    {
        字符串消息=的Request.QueryString [消息];
        字符串的clientId =的Request.QueryString [客户端Id];        AsyncMessageSender发件人=新AsyncMessageSender(客户端ID,消息);
        sender.Start();        的Response.Write(成功);
    }
}

该AsyncMessageSender类:

 公共类AsyncMessageSender
{
    私人的BackgroundWorker BackgroundWorker的;
    私人字符串客户端;
    私人string信息;    公共AsyncMessageSender(字符串客户端ID,字符串消息)
    {
        this.client =的clientId;
        this.msg =消息;        //设置后台线程来听
        backgroundThread =新的BackgroundWorker();
        backgroundThread.WorkerSupportsCancellation = TRUE;
        backgroundThread.DoWork + =新DoWorkEventHandler(backgroundThread_DoWork);
    }    公共无效启动()
    {
        backgroundThread.RunWorkerAsync();
    }    ...
    //之后,它的pretty predictable
}


解决方案

如果你不关心返回任何东西给用户,你可以火起来不是一个单独的线程,或一个快速和肮脏的方法,使用委托和asynchrnously调用它。如果你不关心通知用户当异步任务完成,则可以忽略回调。尝试把一个断点在SomeVeryLongAction()方法的末尾,你会看到它完成运行后,页面已经担任了:

 私人委托无效DoStuff(); //委托行动保护无效的Page_Load(对象发件人,EventArgs的发送)
{}保护无效的button1_Click(对象发件人,EventArgs的发送)
{
    //创建委托
    DoStuff myAction =新DoStuff(SomeVeryLongAction);
    //调用它asynchrnously,控制进到下一条语句
    myAction.BeginInvoke(NULL,NULL);
    Button1.Text = DateTime.Now.ToString();
}
私人无效SomeVeryLongAction()
{
    的for(int i = 0; I< 100;我++)
    {
        //一些很长的工作模拟
        System.Threading.Thread.Sleep(100);
    }
}

I have an asynchronous operation that for various reasons needs to be triggered using an HTTP call to an ASP.NET web page. When my page is requested, it should start this operation and immediately return an acknowledgment to the client.

This method is also exposed via a WCF web service, and it works perfectly.

On my first attempt, an exception was thrown, telling me:

Asynchronous operations are not allowed in this context.
Page starting an asynchronous operation has to have the Async
attribute set to true and an asynchronous operation can only be
started on a page prior to PreRenderComplete event.

So of course I added the Async="true" parameter to the @Page directive. Now, I'm not getting an error, but the page is blocking until the Asynchronous operation completes.

How do I get a true fire-and-forget page working?

Edit: Some code for more info. It's a bit more complicated than this, but I've tried to get the general idea in there.

public partial class SendMessagePage : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string message = Request.QueryString["Message"];
        string clientId = Request.QueryString["ClientId"];

        AsyncMessageSender sender = new AsyncMessageSender(clientId, message);
        sender.Start();

        Response.Write("Success");
    }
}

The AsyncMessageSender class:

public class AsyncMessageSender
{
    private BackgroundWorker backgroundWorker;
    private string client;
    private string msg;

    public AsyncMessageSender(string clientId, string message)
    {
        this.client = clientId;
        this.msg = message;

        // setup background thread to listen
        backgroundThread = new BackgroundWorker();
        backgroundThread.WorkerSupportsCancellation = true;
        backgroundThread.DoWork += new DoWorkEventHandler(backgroundThread_DoWork);
    }

    public void Start()
    {
        backgroundThread.RunWorkerAsync();
    }

    ...
    // after that it's pretty predictable
}

解决方案

If you don't care about returning anything to the user, you can just fire up either a separate thread, or for a quick and dirty approach, use a delegate and invoke it asynchrnously. If you don't care about notifying the user when the async task finishes, you can ignore the callback. Try putting a breakpoint at the end of the SomeVeryLongAction() method, and you'll see that it finishes running after the page has already been served up:

private delegate void DoStuff(); //delegate for the action

protected void Page_Load(object sender, EventArgs e)
{

}

protected void Button1_Click(object sender, EventArgs e)
{
    //create the delegate
    DoStuff myAction = new DoStuff(SomeVeryLongAction); 
    //invoke it asynchrnously, control passes to next statement
    myAction.BeginInvoke(null, null);
    Button1.Text = DateTime.Now.ToString();
}


private void SomeVeryLongAction()
{
    for (int i = 0; i < 100; i++)
    {
        //simulation of some VERY long job
        System.Threading.Thread.Sleep(100);
    }
}

这篇关于通过运行一个ASP.NET网页请求触发的异步操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆