异步等待按钮单击始终同步运行

时间:2016-04-19 07:05:44

标签: c# asp.net multithreading asynchronous async-await

我正在学习异步等待并在我的旧asp.net中实现。我正在使用c#4.6。

现在,在添加async-await后,页面始终以同步方式运行。它等待api发回结果然后在屏幕上显示消息。

我正在寻找的是页面启动一个线程并做出响应(我可以对其进行其他操作)。完成后,它会显示结果。

下面是我的按钮点击,HTTP调用(将启动异步请求)和API方法。

我有

  1. 遵循示例https://msdn.microsoft.com/en-us/library/hh191443.aspx
  2. 在StackOverflow和其他论坛上寻找解决方案。我相信我也是这样做的(当然我不是:()。
  3. 在aspx页面上添加了Async="true"

    按钮单击

    protected async void btnCopy_Click(object sender, EventArgs e)
        {
            await RunAsync(Guid.Parse(SourceBusinessID), Guid.Parse(DestinationBusinessID), false);
    
            if (lblError.Text == "")
            {
                lblError.Text = "Copy Completed!";
            }            
        }
    
    public async Task RunAsync( Guid SourceBusinessID, Guid DestinationBusinessID,bool copyAdviser)
        {
            using (var client = new HttpClient())
            {
                var request = new HttpRequestMessage()
                {
                    RequestUri = new Uri("http://localhost:52140/api/DummyAccounts/"),
                    Method = HttpMethod.Get,
                };
                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
    
                client.Timeout = TimeSpan.FromSeconds(500);
    
                var response = await client.SendAsync(request);
    
                if (!response.IsSuccessStatusCode)
                {                    
                    lblError.Text = response.StatusCode.ToString();
                }
            }
        }
    

    API

    public IHttpActionResult Get(Guid sourceBusinessID, Guid destinationBusinessID,bool copyAdviser = true)
        {
            try
            {
                CopyHelper.SourceBusinessID = sourceBusinessID;
                CopyHelper.DestinationBusinessID = destinationBusinessID;
                CopyHelper.CopyAdviser = copyAdviser;
    
                logger.Info("Copy buisness started:" + DateTime.Now);
    
                bool status = CopyBusinessService.CopyBusiness(CopyHelper.SourceBusinessID, CopyHelper.DestinationBusinessID, CopyHelper.CopyAdviser);
                if (status)
                {
                    logger.Info("Copy business finished:" + DateTime.Now);
    
                    return Ok(true);
                }
                else
                {
                    logger.Info("Copy business failed:" + DateTime.Now);
    
                    return Ok(false);
                }
            }
            catch (Exception ex)
            {
                return InternalServerError(ex);
            }
    
        }
    

    任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:5)

WebForms应用程序中的异步不会使您的表单行为像位于事件循环中的客户端应用程序,并等待事件发生。它仍然是一个服务器呈现页面,它响应由按钮单击或更改事件触发的单个事务性HTTP请求,WebForm通过单个服务器呈现HTML响应。渲染完成后,页面就完成了。没有'事件循环'等待下一次点击。

WebForms / ASP.NET应用程序中的异步只允许您从主线程卸载某些处理,但它不会改变页面上UI的行为。将async视为同时运行多个操作的方法,或者在较长时间运行的IO操作在后台运行时释放主处理线程,然后在呈现最终页面之前返回。

但它对页面实际呈现到浏览器或行为的方式没有任何作用 - WebForms页面仍然是一个纯服务器呈现页面,通过HTTP回发处理事件。就浏览器而言,它是一个事务性请求:无论是否在后端使用Async,都可以单击按钮并重新呈现页面。

解决问题的方法是使用客户端JS框架来管理应用程序的异步流并对服务器进行异步HTTP调用。这将为您提供您正在寻找的行为,其中一个可以在后台运行的长请求,同时让您的客户端应用程序继续执行其他操作。然后,服务器最终会在操作完成后回叫您,然后您可以使用响应数据显示结果或通知用户。

答案 1 :(得分:-3)

我认为你需要做这样的事情:

private void btnCopy_Click (object sender, RoutedEventArgs e)
    {
        Task.Factory.StartNew(async () =>
        {
            await RunAsync (Guid.Parse (SourceBusinessID), Guid.Parse (DestinationBusinessID), false);
            lblError.Dispatcher.Invoke(() => { if (lblError.Text == "") lblError.Text = "Copy Completed!"; });
        });
    }