交叉线程问题?

时间:2011-05-14 03:27:03

标签: c# multithreading

我的错误

  

不进行跨线程操作   有效:访问控制'MailTree'   从线程以外的线程来看它   是在。上创建的。

用我的代码

我的想法是当SaveMail方法完成存储1 mes然后将此mes添加到listview。

private delegate int SaveMailDelegate(ImapX.Message mes);

public int SaveMail(ImapX.Message mess)
{
    if (!File.Exists("D:\\" + Username + "\\" + MailTree.SelectedNode.Text + "\\" + mes.MessageUid.ToString() + ".eml"))
    {
        mess.Process();
        mess.SaveAsEmlToFile("D:\\" + Username + "\\" + MailTree.SelectedNode.Text + "\\", mes.MessageUid.ToString());   //Store messages to a Location 

    }
    // mes.MessageUid=mess.MessageUid;
    return 1;            
}
Mime EncodingMail(string NodeName,string focusitem)
{
    Mime m = new Mime();
    m=Mime.Parse("D:\\" + Username+ "\\"+NodeName+"\\"+focusitem+".eml");
    return m;
}
private void AddMesToMailList()
{
    ListViewItem item = new ListViewItem();
    Mime m = EncodingMail(MailTree.SelectedNode.Text, mes);
    item.Text = mes.MessageUid.ToString();
    item.SubItems.Add(m.MainEntity.Subject);
    ReturnMime(m);
    if (mailfromname != null)
        item.SubItems.Add(mailfromname);
    else item.SubItems.Add(mailfrom);
        item.SubItems.Add(m.MainEntity.Date.ToString());
    item.SubItems.Add(mailfrom);
    MailList.Items.Add(item);
}
private void SaveMailDone(IAsyncResult iar)
{
    SaveMailDelegate del = iar.AsyncState as SaveMailDelegate;
    if (del != null)
    {
        int result = del.EndInvoke(iar);
        AddMesToMailList();            
    }
}    

private void MailTree_AfterSelect(object sender, System.Windows.Forms.TreeViewEventArgs e)
{ 
    MailList.Items.Clear();
    for (int i = 0; i < client.Folders.Count; i++)
    {                          
        (ContextMenuListView.Items[1] as ToolStripMenuItem).DropDownItems[i].Click += new EventHandler(MainForm_Click);
    }
    if (MailTree.SelectedNode.Text == Username)
    {
        webBrowser1.Visible = false;//webBrowser1.DocumentText = "Hello Baby";
        AttachmentList.Visible = false;
        groupBox1.Visible = false;
    }
    else
    {
        webBrowser1.Visible = true;
        groupBox1.Visible = true;

        try
        {
            messages = client.Folders[MailTree.SelectedNode.Text].Search("ALL", false); // Search mail in your choossen Folder
            AmoutOfMail = messages.Count(); //Amout of Mail in this Folder                                         
            for (int i = 0; i < AmoutOfMail; i++)
            {
                mes=messages[i];
                SaveMailDelegate del = new SaveMailDelegate(this.SaveMail);
                del.BeginInvoke(mes, new AsyncCallback(this.SaveMailDone), del);                                      
            }
        }
        catch (Exception)
        { }
    }
}

3 个答案:

答案 0 :(得分:4)

您不能直接从另一个线程访问控件,您必须调用它。

private delegate void ControlCallback(string s);

public void CallControlMethod(string text)
{
    if (control.InvokeRequired)
    {
        ControlCallback call = new ControlCallback((s) =>
        {
            // do control stuff
        });
        control.Invoke(call, new object[] { text });
    }
    else
    {
        // do control stuff
    }
}

答案 1 :(得分:1)

我认为AddMesToMailList()正在尝试修改视图元素,但它是在一个错误的线程上。

尝试这样的事情

void AddMesToMailList()
{
    if (this.InvokeRequired)
    {
         this.BeginInvoke(new Action(AddMesToMailList));
         return;
    }

    // do stuff that original  AddMesToMailList() did.
}

编辑:        SaveMail有点复杂,因为它有一个返回值,但你可以尝试这个

public int SaveMail(ImapX.Message mess)
{
     if(this.InvokeRequired)
     {
            return (int) this.Invoke(
                   new Func<ImapX.Message, int>( m => SaveMail(mess)) );
     }
     else
     {

        if (!File.Exists(@"D:\" + Username + "\\" + MailTree.SelectedNode.Text + "\\" + mes.MessageUid.ToString() + ".eml"))
        {
            mess.Process();
            mess.SaveAsEmlToFile(@"D:\" + Username + "\\" + MailTree.SelectedNode.Text + "\\", mes.MessageUid.ToString());   //Store messages to a Location 

        }
       // mes.MessageUid=mess.MessageUid;
        return 1;  

     }



}

答案 2 :(得分:1)

您无法在与创建的线程不同的线程上访问UI。从辅助线程(运行回调处理程序的线程)内部,您需要调用Form.BeginInvoke来注册将在UI线程上运行的方法。从该方法,您可以更新UI控件