在循环中多次异步方法调用方法

时间:2010-03-12 13:49:47

标签: c# asp.net web-services asynchronous webforms

我花了一整天的时间尝试使用'AddOnPreRenderCompleteAsync'和'RegisterAsyncTask',但到目前为止没有成功。

我使用'BeginExecuteReader'和'EndExecuteReader'成功调用了数据库异步,但是缺少这一点。异步处理不应该是对DB的调用,在我的情况下,它应该是快速的,在调用外部Web服务时,应该在'while'循环期间调用。

我认为简化的伪代码最好解释:
(注意:连接字符串使用'MultipleActiveResultSets')

private void MyFunction()
{
    "Select ID, UserName from MyTable"
    // Open connection to DB
    ExecuteReader();
    if (DR.HasRows)
    {
        while (DR.Read())
        {
            // Call external web-service
            // and get current Temperature of each UserName - DR["UserName"].ToString()
            // Update my local DB 
            Update MyTable set Temperature = ValueFromWebService where UserName = 
                    DR["UserName"];

            CmdUpdate.ExecuteNonQuery();
        }

        // Close connection etc
    }
}

访问数据库很快。从外部Web服务获取返回的结果很慢,至少应该处理Asynchnously。

如果每次调用Web服务只需1秒钟,假设我只有100个用户,则完成数据库更新至少需要100秒,这显然不是一个选项。
最终应该有成千上万的用户(目前只有2个)。

目前一切正常,只是非常同步:)
对自己的想法:
也许我接近这个的方式是错的?
也许整个过程应该被称为Asynchnously?

很多人

4 个答案:

答案 0 :(得分:1)

你有没有考虑将这一切都转移到它自己的线程中?

答案 1 :(得分:0)

你真正关心的是什么?

避免长期任务阻止您的应用程序? 如果是这样,您可以使用线程(请参阅BackgroundWorker)

并行处理几次对Web服务的调用以加快整体思考? 如果是这样,也许可以异步调用Web服务来提供回调。您也可以使用ThreadPool或Tasks。但在继续进行数据库更新之前,您必须设法等待所有调用或任务完成。

答案 2 :(得分:0)

您应该尽可能短的时间保持数据库连接处于打开状态。因此,在迭代DataReader时不要做东西。大多数应用程序开发人员更喜欢将他们的实际数据库访问代码放在单独的层上,在这种情况下,您可以将DataTable或类型集合返回给调用代码。此外,如果要更新正在读取的同一个表,则可能会导致锁定。

一次会有多少用户执行此方法,以及需要多长时间刷新一次?您确定需要在Web应用程序内执行此操作吗?您可以考虑使用单例来实现这一点,在这种情况下,即使在Web应用程序中,分离几个工作线程也是完全合适的。另一件需要考虑的事情是使用Windows服务,我认为这更适合于通过Web服务定期更新数据,而该服务甚至与当前用户的会话无关。

答案 3 :(得分:0)

我想说,为每个webrequest创建一个线程,并执行以下操作:

额外功能:

int privCompleteThreads = 0;
int OpenThreads = 0;
int CompleteThreads
{
  get{ return privCompleteThreads; }
  set{ privCompleteThreads = value; CheckDoneOperations(); }
}
void CheckDoneOperations
{
  if(CompleteThreads == OpenThreads)
  {
    //done!
  }
}

在主程序中:

foreach(time i need to open a request)
{
  OpenThreads = OpenThreads + 1;
  //Create thread here
}

在线程函数内部:

//do your other stuff here

//do this when done the operation:
CompleteThreads = CompleteThreads + 1;

现在我不确定这种方法有多可靠,取决于你。但正常的网页请求不应该花一秒钟,你的浏览器不会在第二次加载这个页面吗?我的装载速度和F5一样快。它只是打开一个流,您可以尝试打开一次Web请求,并一遍又一遍地使用相同的实例,看看是否能加快它的速度