C#2.0函数在单独线程中调用时不起作用
我有一个函数可以从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);
}
}
}
任何想法?
感谢 普拉卡什
也许你需要的一个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();
也许这也会解决您的问题。
是的,这是可能的问题。但是STA线程也需要消息循环。 OP的代码在没有一个的情况下仍然死锁的可能性很大。使用Application.Run()。 – 2010-10-13 12:24:29
我在ApartmentState.STA模式的线程中调用了该函数,它工作正常。谢谢testalino。 – Prakash 2010-10-19 05:09:58
你的线程应该是类成员而不是方法变量。
当您的方法完成时,线程变量超出范围,可能会无法完成清理。
线程是顶级(根)对象,不会因为变量超出范围而终止。 – 2010-10-13 10:50:53
您试图访问非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;
这是准确的,但实际上并不是问题所在。 Text属性是特殊的,它被缓存,实际上可以从工作线程读取(但不能写入)。 – 2010-10-13 12:22:27
@Hans,我怀疑,但我仍然会检查它。 – 2010-10-14 11:11:33
只有他们在您的第二个线程创建的控制和参考的.Text
性质的副本。
如果您使用不同的线程访问任何控件,您将锁定您的应用程序或发生异常。
其他解决方法是使用.Invoke()
,但在你的情况下,你真的不需要去那里。
但是,我怀疑这是否是主要原因:您甚至不应该在非UI线程上讨论所有那些'.Text'属性。理想情况下,您应该先获得并将其传递给工作人员。 – 2010-10-13 10:46:56