Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# asp.net v4中的异步任务内部循环_C#_Asp.net_Asynchronous_Async Await - Fatal编程技术网

C# asp.net v4中的异步任务内部循环

C# asp.net v4中的异步任务内部循环,c#,asp.net,asynchronous,async-await,C#,Asp.net,Asynchronous,Async Await,我使用的是asp.net v4 c#,我有一个电子邮件地址列表。我希望我的一个管理员能够键入一条消息,按“发送”,然后让电子邮件一个接一个地发送出去 我认为最好的方法是使用.net中的异步方法?单击send按钮,我获取电子邮件地址列表,然后调用async方法。我只是不知道如何让它一个接一个地循环浏览列表,然后发送电子邮件 需要一次完成一个,以便我可以保存针对该用户帐户发送的电子邮件副本 以下是我到目前为止所做的(从这里的教程/帖子拼凑而成) protectedvoidbtnsend\u单击(对象

我使用的是asp.net v4 c#,我有一个电子邮件地址列表。我希望我的一个管理员能够键入一条消息,按“发送”,然后让电子邮件一个接一个地发送出去

我认为最好的方法是使用.net中的异步方法?单击send按钮,我获取电子邮件地址列表,然后调用async方法。我只是不知道如何让它一个接一个地循环浏览列表,然后发送电子邮件

需要一次完成一个,以便我可以保存针对该用户帐户发送的电子邮件副本

以下是我到目前为止所做的(从这里的教程/帖子拼凑而成)

protectedvoidbtnsend\u单击(对象发送者,事件参数e)
{
//获取电子邮件地址列表并发送给他们
//一旦测试comp,这些将来自数据库
列表电子邮件=新列表();
电子邮件。添加(“test1@test.com");
电子邮件。添加(“test2@test.com");
电子邮件。添加(“test3@test.com");
电子邮件。添加(“test4@test.com");
电子邮件。添加(“test5@test.com");
电子邮件。添加(“test6@test.com");
电子邮件。添加(“test7@test.com");
SendingDelegate worker=新的SendingDelegate(DoSend);
AsyncCallback completedCallback=新的AsyncCallback(DoSendCompletedCallBack);
lblThreadDetails.Text=“发送至”+电子邮件.Count.ToString()+“电子邮件地址”;
worker.BeginInvoke(completedCallback,AsyncOperationManager.CreateOperation(null));
发送=真;
}
//指示异步任务是否正在运行的布尔标志
私有布尔发送=假;
私有委托bool SendingDelegate();
二等兵布尔·多森德()
{
//发送消息
//每次在此处发送并保存在数据库中的电子邮件
//在屏幕上给用户一些反馈。X应该是电子邮件地址。
lblThreadDetails.Text=“处理”+x.ToString();
睡眠(1000);
返回false;
}
私有void DoSendCompletedCallBack(IAsyncResult ar)
{
//获取原始工作代理和AsyncOperation实例
SendingDelegate工作者=(SendingDelegate)((AsyncResult)ar).AsyncDelegate;
//完成异步操作
bool success=worker.EndInvoke(ar);
发送=假;
如果(成功)
{
//完成爬网后立即执行sql任务
lblThreadDetails.Text=“全部完成!”;
}
}
我基本上需要将异步函数的调用放入一个循环中,在这个循环中我遍历电子邮件地址列表


这种方法有意义吗?

我认为您无法使用ASP.NET 4.5和
async/await
,这可能是解决这种情况的理想方法(有关更多信息,请参阅和)

但是,使用ASP 4.0,您仍然可以在页面上使用异步代码和
page.RegisterAsyncTask
。这将延长请求的生命周期,直到异步任务完成:

PageAsyncTask asyncTask = new PageAsyncTask(
    slowTask.OnBegin, slowTask.OnEnd, slowTask1.OnTimeout, 
    "AsyncTaskName", true);
然后从
OnBegin/OnEnd
调用
worker.BeginInvoke/EndInvoke
。MSDN对此有一个明确的定义

解决问题本身:

这种方法有意义吗?谢谢你提供的任何信息

如果我正确理解了您的代码,我认为这没有意义

显然,您在这里所做的是启动一个后台线程并在此线程上执行一些同步操作,如
thread.Sleep(1000)
DoSend()中执行。这对于客户端UI应用程序来说是有意义的(以保持UI的响应性)

但是,对于您的服务器端应用程序,您并没有获得任何优势:至少有一个线程(以
BeginInvoke
开头的线程)在您正在进行的操作期间仍然被阻止

您也可以直接在处理HTTP请求的原始线程上调用
DoSend()
(在
btnSend\u单击
)而不调用
BeginInvoke
。在这种情况下,你的应用程序甚至可以更好地扩展,因为它的线程切换更少


现在,也许您可以重新考虑代码,使用纯异步IO/网络绑定API,而不需要专用线程。这将使你的应用程序更好地扩展。阅读我的博客文章,更好地了解我所说的内容。

Tangent:你知道你真的不需要
新建
委托对象了吗?至少对我来说,这会使代码更具可读性,因为您不需要追溯到委托变量指向的位置。您可以使用
(DoSend as Action).BeginInvoke(DoSendCompletedCallback,AsyncOperationManager.CreateOperation(null))
此外,您的方法中存在一个突出的问题,而不是您的测试工具,它正在从后台操作更新GUI。大多数GUI系统都是单线程的,即创建和更新UI必须在运行事件循环的线程上进行。我会尝试使用
Task.Run()
async..wait
功能,但我不熟悉它,现在没有时间准备和测试代码以获得答案,所以你只能接受这个建议。我已经编辑了你的标题。请参阅“”,其中的共识是“不,他们不应该”。
PageAsyncTask asyncTask = new PageAsyncTask(
    slowTask.OnBegin, slowTask.OnEnd, slowTask1.OnTimeout, 
    "AsyncTaskName", true);