C#2.0函数在单独的线程中调用时不起作用

时间:2010-10-13 10:38:56

标签: c# multithreading c#-2.0

我有一个从DocuShare服务器下载mailmessage作为MSG文件的功能。从主线程调用时,该函数可以正常工作。但是,当我在一个单独的线程中调用该函数时,下载失败。当我介入代码时,我可以看到函数被调用,所有参数都被正确计算,返回值是我所期望的。不幸的是,我看到,没有文件被下载。

代码:

    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);
            }
        }
    }

有什么想法吗?

由于 普拉卡什

4 个答案:

答案 0 :(得分: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();

也许这也可以解决你的问题。

答案 1 :(得分:1)

您正尝试在非UI线程中访问Control的属性

例如在行中,

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

您正尝试在不同的线程中访问UI Control的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;   

答案 2 :(得分:0)

您的主题应该是类成员而不是方法变量。

当您的方法完成时,线程变量超出范围并且可以在不完成的情况下进行清理。

答案 3 :(得分:0)

创建控件的.Text属性的副本,并在第二个线程中仅引用它们。

如果您使用不同的线程访问任何控件,您将锁定您的应用程序或获取异常。

其他方式是使用.Invoke(),但在你的情况下,你真的不需要去那里。