2010-10-13 43 views
1

我有一個函數可以從DocuShare服務器下載郵件消息作爲MSG文件。當從主線程調用該函數時,該函數完美工作。但是,當我在一個單獨的線程中調用該函數時,下載失敗。當我介入代碼時,我可以看到該函數正在被調用,所有參數都被正確計算,返回值就是我所期望的。不幸的是,我看到,沒有文件被下載。C#2.0函數在單獨線程中調用時不起作用

代碼:

private void btnDownloadMails_Click(object sender, EventArgs e) 
    { 

     //Thread t = new Thread(new ThreadStart(DownloadMailAsMsg)); 
     //t.Start(); //Does not work 

     DownloadMailAsMsg(); // Works fine   
    } 

    void DownloadMailAsMsg() 
    { 

     DSServerMap.Server dsserver = new DSServerMap.Server(); 
     if (!SelectMappedServer(ref dsserver, textServer.Text.ToString())) 
      return; 

     long status = 0;    
     dsserver.DocuShareAddress = textServer.Text; 
     dsserver.UserName = textUser.Text; 
     dsserver.Password = textPwd.Text; 
     status = dsserver.Logon(); 

     if (status == 0) 
     { 
      IItemObj objParentItem; 
      string[] emailHan = { "MailMessage-12", "MailMessage-13", "MailMessage-31" }; 
      foreach (string handnum in emailHan) 
      { 
       objParentItem = (IItemObj)dsserver.CreateObject(handnum); 
       DSGATEWAYLib.IGatewayHandler gateway = (DSGATEWAYLib.IGatewayHandler)dsserver.Open(); 

       objParentItem.AttachGateway(gateway, true); 
       objParentItem.Name = @"D:\em\m_" + handnum + ".msg";      
       int flag = objParentItem.DSDownload(0); 
      } 
     } 
    } 

任何想法?

感謝 普拉卡什

+1

但是,我懷疑這是否是主要原因:您甚至不應該在非UI線程上討論所有那些'.Text'屬性。理想情況下,您應該先獲得並將其傳遞給工作人員。 – 2010-10-13 10:46:56

回答

4

也許你需要的一個STA線程。我有一個類似的問題一次,以下解決了我的問題:

Thread t = new Thread((ThreadStart)delegate 
         { // MAPI does only work in STA threads. Therefore an STA thread needs to be created explicitly for the SendMail call. 
          //...do work here 
         }); 
t.SetApartmentState(ApartmentState.STA); 
t.Start(); 

也許這也會解決您的問題。

+0

是的,這是可能的問題。但是STA線程也需要消息循環。 OP的代碼在沒有一個的情況下仍然死鎖的可能性很大。使用Application.Run()。 – 2010-10-13 12:24:29

+0

我在ApartmentState.STA模式的線程中調用了該函數,它工作正常。謝謝testalino。 – Prakash 2010-10-19 05:09:58

0

你的線程應該是類成員而不是方法變量。

當您的方法完成時,線程變量超出範圍,可能會無法完成清理。

+0

線程是頂級(根)對象,不會因爲變量超出範圍而終止。 – 2010-10-13 10:50:53

1

您試圖訪問非UI線程控件的屬性,

例如線,

dsserver.DocuShareAddress = textServer.Text; 
    dsserver.UserName = textUser.Text; 
    dsserver.Password = textPwd.Text; 

你想在不同的線程,這實際上拋出一個異常訪問UI控件的Text屬性。

要在不同線程中訪問控件的每個值,必須將其包含在某種參數中並將其傳遞給線程。

class MyServerParameters{ 
    string Server; 
    string Username; 
    string Password; 
} 


private void btnDownloadMails_Click(object sender, EventArgs e)  
{  

    MyServerParameters p = new MyServerParameters(); 
    // we are still in UI thread so copy your values 
    // to p 
    p.Server = textServer.Text;   
    p.Username = textUser.Text;   
    p.Password = textPwd.Text;   
    Thread t = new Thread(new ParametricThreadStart(DownloadMailAsMsg));  
    // pass p to another thread 
    t.Start(p); // this will work... 

} 


void DownloadMailAsMsg(object mp) 
{ 
    // access p back like this... 
    MyServerParameters p = mp as MyServerParameters; 


    dsserver.DocuShareAddress = p.Server;  
    dsserver.UserName = p.Username;  
    dsserver.Password = p.Password; 
+0

這是準確的,但實際上並不是問題所在。 Text屬性是特殊的,它被緩存,實際上可以從工作線程讀取(但不能寫入)。 – 2010-10-13 12:22:27

+0

@Hans,我懷疑,但我仍然會檢查它。 – 2010-10-14 11:11:33

0

只有他們在您的第二個線程創建的控制和參考的.Text性質的副本。

如果您使用不同的線程訪問任何控件,您將鎖定您的應用程序或發生異常。

其他解決方法是使用.Invoke(),但在你的情況下,你真的不需要去那裏。

相關問題