我有一个网址表,我需要循环遍历、下载每个文件、更新表并返回结果。我想一次运行最多 10 个下载,因此我正在考虑使用委托(delegate),如下所示:
DataTable photos;
bool scanning = false,
complete = false;
int rowCount = 0;
public delegate int downloadFileDelegate();
public void page_load(){
photos = Database.getData...
downloadFileDelegate d = downloadFile;
d.BeginInvoke(downloadFileComplete, d);
d.BeginInvoke(downloadFileComplete, d);
d.BeginInvoke(downloadFileComplete, d);
d.BeginInvoke(downloadFileComplete, d);
d.BeginInvoke(downloadFileComplete, d);
while(!complete){}
//handle results...
}
int downloadFile(){
while(scanning){} scanning = true;
DataRow r;
for (int ii = 0; ii < rowCount; ii++) {
r = photos.Rows[ii];
if ((string)r["status"] == "ready"){
r["status"] = "running";
scanning = false; return ii;
}
if ((string)r["status"] == "running"){
scanning = false; return -2;
}
}
scanning = false; return -1;
}
void downloadFileComplete(IAsyncResult ar){
if (ar == null){ return; }
downloadFileDelegate d = (downloadFileDelegate)ar.AsyncState;
int i = d.EndInvoke(ar);
if (i == -1){ complete = true; return; }
//download file...
//update row
DataRow r = photos.Rows[i];
r["status"] = "complete";
//invoke delegate again
d.BeginInvoke(downloadFileComplete, d);
}
但是,当我运行此命令时,运行 5 所需的时间与运行 1 所需的时间相同。我预计它会快 5 倍。
有什么想法吗?
最佳答案
您看起来正在尝试使用无锁同步(使用 while(scanning)
检查在函数开始时设置的 bool 值并在结束时重置),但所有这些都成功了所做的只是一次只运行一次检索。
- 您是否有理由不希望它们同时运行?这似乎是你练习的全部要点。我看不出其中的原因,所以我会完全丢失
扫描
标志(以及相关的逻辑)。 - 如果您打算采用这种方法,您的 bool 标志需要声明为
volatile
(否则它们的读取可能会被缓存,您可能会无休止地等待) - 您的数据更新操作(更新
DataRow
中的值)必须在 UI 线程上进行。您必须将这些操作封装在Control.Invoke
或Control.BeginInvoke
调用中,否则您将跨线程边界与控件进行交互。 BeginInvoke
返回一个AsyncWaitHandle
。将其用于操作全部完成时将发生的逻辑。像这样的东西
-
WaitHandle[] handles = new WaitHandle[]
{
d.BeginInvoke(...),
d.BeginInvoke(...),
d.BeginInvoke(...),
d.BeginInvoke(...),
d.BeginInvoke(...)
}
WaitHandle.WaitAll(handles);
这将导致调用线程阻塞,直到所有操作完成。
关于c# - 在 C# 中异步运行多个委托(delegate)并等待响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2365718/