我目前正在执行一项需要花费大量时间的任务。 基本上,我想要做的是在foreach循环中运行多个任务。 我尝试使用Parallel.ForEach来冻结我的UI。我希望能够一次打电话给10个uid。
foreach (var uid in listBox2.Items)
{
if (StopEmail) break;
Application.DoEvents();
string jsonstring = GetEmails(uid.ToString(), token);
if (jsonstring != null)
{
label6.Text = " Current UID: " + listBox2.Items.IndexOf(uid);
dynamic jsonResponse = JsonConvert.DeserializeObject(jsonstring);
string idstt = jsonResponse["email"];
if (idstt != null)
{
listBox3.Items.Add(idstt);
label4.Text = "Total Emails: " + listBox3.Items.Count.ToString();
}
}
}
这是我的Parallel.ForEach代码:
var files = listBox2.Items.Cast<String>().ToList();
Parallel.ForEach(files, uid =>
{
Application.DoEvents();
string jsonstring = GetEmails(uid.ToString(), token);
if (jsonstring != null)
{
this.Invoke(new MethodInvoker(delegate()
{
label6.Text = " Current UID: " + listBox2.Items.IndexOf(uid);
}));
dynamic jsonResponse = JsonConvert.DeserializeObject(jsonstring);
string idstt = jsonResponse["email"];
if (idstt != null)
{
this.Invoke(new MethodInvoker(delegate()
{
listBox3.Items.Add(idstt);
label4.Text = "Total Emails: " + listBox3.Items.Count.ToString();
}));
}
}
});
答案 0 :(得分:2)
以下是我采用的方法 - 使用Microsoft的Reactive Framework(NuGet&#34; System.Reactive.Windows.Forms&#34;)。
然后你可以这样做:
package com.example.guestbook;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import java.io.IOException;
import java.util.Date;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class GuestbookServlet extends HttpServlet {
@Override
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
Entity entity0 = new Entity("Dummy", "abc");
entity0.setProperty("created", new Date());
datastore.put(entity0);
Entity entity1 = new Entity("Dummy", "xyz");
entity1.setProperty("created", null);
datastore.put(entity1);
}
}
慢速部分位于var uids = listBox2.Item.Cast<String>().ToArray();
var query =
from uid in uids.ToObservable()
from jsonstring in Observable.Start(() => GetEmails(uid, token))
where jsonstring != null
select new { uid, jsonstring };
IDisposable subscription =
query
.ObserveOn(this)
.Subscribe(x =>
{
label6.Text = " Current UID: " + listBox2.Items.IndexOf(x.uid);
dynamic jsonResponse = JsonConvert.DeserializeObject(x.jsonstring);
string idstt = jsonResponse["email"];
if (idstt != null)
{
listBox3.Items.Add(idstt);
label4.Text = "Total Emails: " + listBox3.Items.Count.ToString();
}
});
调用中,因此GetEmails
处理得很好。
query
调用会将代码编组回UI线程,因此不需要调用.ObserveOn(this)
次调用。
最后,为了尽早结束计算,只需调用.Invoke
。
答案 1 :(得分:0)
将Parallel.ForEach
换入Task.Run
来电:
var files = listBox2.Items.Cast<String>().ToList();
Task task = Task.Run( () => {
Parallel.ForEach( files, uid =>
{
// remove the `Application.DoEvents()` call, it is unnecessary
// ...
}
} );
相反,从ForEach
方法返回数据而不是调用.Invoke
可能是更好的设计,这样您就可以使用await
并在一次转发时更新UI ForEach
已完成 - 但这取决于循环的性质和所需的用户体验。