C# Task Parallel Library 第一次慢
C# Task Parallel Library first time slow
尝试并行执行多个 HTTP Get 请求,每个任务一个。如果我通过 Internet Explorer 执行 Gets,它们几乎会立即 return,但是当通过任务调用代码时,我第一次启动它们时,它们会花费好几秒钟才能 return,但是 运行 如我所料,他们第二次 return。所以要么我正在做一些阻塞的事情,要么由于某种原因线程没有启动?第一次尝试使用TPL
这是基本查找 class:
public class Lookup
{
public string Name { get; set; }
public string URL { get; set; }
public Lookup(string Name, string URL)
{
this.Name = Name;
this.URL = URL;
}
public LookupReturn DoLookup()
{
LookupReturn d = new LookupReturn();
d.Name = this.Name;
d.URL = this.URL;
WebRequest wrGETURL;
wrGETURL = WebRequest.Create(this.URL);
Stream objStream;
objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string sLine = objReader.ReadToEnd();
d.Result = sLine;
return d;
}
}
而 return 类型就是:
public class LookupReturn
{
public string Name { get; set; }
public string Result { get; set; }
public string URL { get; set; }
}
因此,尝试运行并行执行此操作 - 从 Winforms GUI 进行测试,但最终将在 WCF 服务中进行。
public partial class Form1 : Form
{
private List<Lookup> Lookups = new List<Lookup>();
private async void btnRunLookups_Click(object sender, EventArgs e)
{
Lookups.Add(new Lookup("Name1", "http://geturl1 "));
Lookups.Add(new Lookup("Name2", "http://geturl2 "));
// More lookups…
int workerThreads, complete;
ThreadPool.GetMinThreads(out workerThreads, out complete);
ThreadPool.SetMinThreads(100, complete);
btnRunLookups.Visible = false;
List <Task<LookupReturn>> lookupTasks = new List<Task<LookupReturn>>();
foreach(Lookup dl in Lookups)
{
lbLookups.Items.Add("Starting task for " + dl.URL);
Task<LookupReturn> t = new Task<LookupReturn>(() => dl.DoLookup() );
lookupTasks.Add(t);
t.Start();
}
//await Task.WhenAny(
// Task.WhenAll(lookupTasks.ToArray<Task<LookupReturn>>()),
// Task.Delay(3000)
// );
// This takes a good few seconds the first time
await Task.WhenAll(lookupTasks.ToArray<Task<LookupReturn>>());
// Now I need to see which ones completed and returned a result
foreach (var x in lookupTasks)
{
if (x.IsCompleted)
{
lbLookups.Items.Add(x.Result);
}
else
{
// lbLookups.Items.Add("Not finished " + x.Result.Name);
}
}
btnRunLookups.Visible = true;
}
Other people 注意到 HttpWebRequest
第一次请求可能需要很长时间,因为它正在寻找代理信息。尝试将其 Proxy
属性 设置为空。
wrGETURL = WebRequest.Create(this.URL);
wrGETURL.Proxy = null;
问题很可能是程序在第一次调用 GetResponse
时进行了一些首次设置(DNS 解析、代理检测等)。特别是代理检测,可能需要很长时间。
尝试并行执行多个 HTTP Get 请求,每个任务一个。如果我通过 Internet Explorer 执行 Gets,它们几乎会立即 return,但是当通过任务调用代码时,我第一次启动它们时,它们会花费好几秒钟才能 return,但是 运行 如我所料,他们第二次 return。所以要么我正在做一些阻塞的事情,要么由于某种原因线程没有启动?第一次尝试使用TPL
这是基本查找 class:
public class Lookup
{
public string Name { get; set; }
public string URL { get; set; }
public Lookup(string Name, string URL)
{
this.Name = Name;
this.URL = URL;
}
public LookupReturn DoLookup()
{
LookupReturn d = new LookupReturn();
d.Name = this.Name;
d.URL = this.URL;
WebRequest wrGETURL;
wrGETURL = WebRequest.Create(this.URL);
Stream objStream;
objStream = wrGETURL.GetResponse().GetResponseStream();
StreamReader objReader = new StreamReader(objStream);
string sLine = objReader.ReadToEnd();
d.Result = sLine;
return d;
}
}
而 return 类型就是:
public class LookupReturn
{
public string Name { get; set; }
public string Result { get; set; }
public string URL { get; set; }
}
因此,尝试运行并行执行此操作 - 从 Winforms GUI 进行测试,但最终将在 WCF 服务中进行。
public partial class Form1 : Form
{
private List<Lookup> Lookups = new List<Lookup>();
private async void btnRunLookups_Click(object sender, EventArgs e)
{
Lookups.Add(new Lookup("Name1", "http://geturl1 "));
Lookups.Add(new Lookup("Name2", "http://geturl2 "));
// More lookups…
int workerThreads, complete;
ThreadPool.GetMinThreads(out workerThreads, out complete);
ThreadPool.SetMinThreads(100, complete);
btnRunLookups.Visible = false;
List <Task<LookupReturn>> lookupTasks = new List<Task<LookupReturn>>();
foreach(Lookup dl in Lookups)
{
lbLookups.Items.Add("Starting task for " + dl.URL);
Task<LookupReturn> t = new Task<LookupReturn>(() => dl.DoLookup() );
lookupTasks.Add(t);
t.Start();
}
//await Task.WhenAny(
// Task.WhenAll(lookupTasks.ToArray<Task<LookupReturn>>()),
// Task.Delay(3000)
// );
// This takes a good few seconds the first time
await Task.WhenAll(lookupTasks.ToArray<Task<LookupReturn>>());
// Now I need to see which ones completed and returned a result
foreach (var x in lookupTasks)
{
if (x.IsCompleted)
{
lbLookups.Items.Add(x.Result);
}
else
{
// lbLookups.Items.Add("Not finished " + x.Result.Name);
}
}
btnRunLookups.Visible = true;
}
Other people 注意到 HttpWebRequest
第一次请求可能需要很长时间,因为它正在寻找代理信息。尝试将其 Proxy
属性 设置为空。
wrGETURL = WebRequest.Create(this.URL);
wrGETURL.Proxy = null;
问题很可能是程序在第一次调用 GetResponse
时进行了一些首次设置(DNS 解析、代理检测等)。特别是代理检测,可能需要很长时间。