为什么代码不在自己的线程中运行?

时间:2014-01-19 16:32:50

标签: c# wpf multithreading

我正在尝试运行此代码( 正在运行):

foreach(Friend f in chatLib.Friends)
{
    chatLib.GetPhoto(f);
    contactWindowControl.AddContactToList(f);
}

在它自己的主题中,以便不阻止UI 我试过以下:

chatLib.Friends.ForEach(item => 
    new Thread(() => { 
        Dispatcher.BeginInvoke(new Action<Friend>(chatLib.GetPhoto), item); 
        Dispatcher.BeginInvoke(new Action<Friend>(contactWindowControl.AddContactToList), item); 
    })
);

我也试过没有 Lambda

GetPhoto (来自聊天图书馆)

public void GetPhoto(Friend contact)
{
    VcardIq viq = new VcardIq(IqType.get, new Jid(contact.jid));
    IQ iq = xmpp.IqGrabber.SendIq(viq);

    if (iq != null && iq.Type == IqType.result)
    {
        Vcard vcard = iq.Vcard;
        if (vcard != null)
        {
            contact.photo = vcard.Photo.Image;
            contact.hasPhoto = true;
        }
    }
}

AddContactToList (来自usercontrol后面的代码)

public void AddContactToList(Friend contact)
{
    contactScroll.Children.Add(new ContactWindowContact(contact));
}

2 个答案:

答案 0 :(得分:1)

因为你在线程中什么都不做,基本上你是说创建一个新线程,然后用Dispatcher注册代码,以便代码在UI线程上运行。

没有神奇的“make things threaded”,你正在做什么创建一个线程,然后将你想要做的工作推回原来的线程。

您需要做的是制作代码,以便getphoto返回您需要的内容,并且不会更新UI线程上使用的任何内容(因此任何绑定到xaml /树中任何内容的内容),然后当您完成此操作时工作调用调度程序只传递代码来更新数据

此外你真的不应该为此创建自己的线程,只是使用任务或更好,因为你已经使用foreach切换到parallel.foreach

Parallel.Foreach(chatLib.Friends,item=>
{
    // This runs in parallel, do the expensive work here and NOT Inside Dispatcher
    item.Photo = chatLib.getPhoto(item);

    Dispatcher.BeginInvoke(()=>
    {
        // This will run on the UI thread, only do updates here
        contactWindowControl.AddContactToList(item);
    });
});

答案 1 :(得分:0)

我认为最好使用任务而不是调度程序。

您的代码如下所示:

List<Task> tasks = new List<Task>();
foreach(Friend f in chatLib.Friends)
{
    Task task = Task.Factory.StartNew( ( arg ) => 
    {chatLib.GetPhoto(arg); contactWindowControl.AddContactToList(arg); }, f );
    tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());