我在下载系统上工作,一次下载最多4个文件,如果下载时出错,则重试最多5次。 我希望它在完成下载后用变量调用不同的回调。
这就是我写的:
private void Download(string url, (something) callback)
{
if (asyncworkers++ < Global.paralleldownloads -1) // async download
{
using (WebClient client = new WebClient())
{
client.Proxy = (Global.proxymode == 2 ? new WebProxy(dynamicproxy) : (Global.proxymode == 1 ? new WebProxy(Global.proxy) : null));
System.Timers.Timer timer = new System.Timers.Timer(5000);
timer.Enabled = true;
client.DownloadStringCompleted += (sender, e) =>
{
asyncworkers--;
if (timer.Enabled)
{
timer.Stop();
if (e.Error == null && e.Result.Length > 0)
{
AppendTextBox("successful async\r\n");
errors = 0;
//call "callback" and its variables here
}else{
AppendTextBox("empty async\r\n");
if (errors++ > 3)
{
//stop trying
}else{
Download(url, callback);
}
}
}
};
client.DownloadStringAsync(new Uri(url));
timer.Elapsed += (sender, e) =>
{
AppendTextBox("timeout async\r\n");
timer.Enabled = false;
client.CancelAsync();
Download(url, callback);
};
}
}else{ // sync download to delay it
var request = WebRequest.Create(url);
request.Proxy = (Global.proxymode == 2 ? new WebProxy(dynamicproxy) : (Global.proxymode == 1 ? new WebProxy(Global.proxy) : null));
request.Timeout = 5000;
using (var response = request.GetResponse())
{
using (var stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream))
{
string data = reader.ReadToEnd();
if (data.Length > 0)
{
AppendTextBox("successful sync\r\n");
asyncworkers--;
errors = 0;
//call "callback" and its variables here
return;
}
}
}
}
asyncworkers--;
AppendTextBox("error sync\r\n");
if (errors++ > 3)
{
//stop trying
}else{
Download(url, callback);
}
}
}
这就是我想用它的方式:
Download("http://.....", GetDataDone(var1, var2, var3, var4));
或
Download("http://.....", UpdateDone());
我希望我所描述的至少对你来说有点清楚。我怎么能按照我希望的方式工作呢?谢谢!
答案 0 :(得分:1)
将callback
声明为Action<T1,T2,T3,T4>
,其中T1
是var1
的类型,T2
是var2
等等。调用这样的回调:
public void Download(string url, Action<T1,..> callback)
{
//....
callback(var1,var2,var3,var4);
//...
}
将具有匹配签名按名称的函数作为回调传递或使用lambda来匹配签名:
public void OnDownload(T1 var1, T2 var2, T3 var3, T4 var4)
{
// do stuff here
}
//later
Download("http...", OnDownload);
评论后更新
使用lambda表达式预先传递参数:
public void Download(string url, Action callback)
{
//...
callback();
//..
}
Download("http://..", () => OnDownload(42, "request", user, 0.5f));