问题
I am using background worker in my Application
my code for this
void CreateThreadForEachServer()
{
DataAccess oDA = new DataAccess();
List<Server> allServerData = oDA.GetAllServers();
foreach (Server serverData in allServerData)
{
backgroundWorker = new BackgroundWorker();
backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
backgroundWorker.RunWorkerAsync(serverData);
}
}
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
Server server = (Server)e.Argument;
CreateSnapshotForEachServer(server);
}
void CreateSnapshotForEachServer(Server server)
{
DataAccess oDA = new DataAccess();
MsmqMessageFormat message = new MsmqMessageFormat();
try
{
message = new Queue().ReadMessageFromMSMQ(server.ServerName);
}
catch
{
}
}
My problem is when I am calling this method
try
{
message = new Queue().ReadMessageFromMSMQ(server.ServerName);
}
catch
{
}
in a background worker then i can not able to call this method just read a message from MSMQ
But when i can't use background worker just call this method in simple thread like this
void CreateThreadForEachServer()
{
DataAccess oDA = new DataAccess();
List<Server> allServerData = oDA.GetAllServers();
foreach (Server serverData in allServerData)
{
ThreadStart t = delegate { CreateSnapshotForEachServer(serverData); };
Thread td = new Thread(t);
td.Priority = ThreadPriority.Highest;
td.Start();
}
}
then this method call properly
try
{
message = new Queue().ReadMessageFromMSMQ(server.ServerName);
}
catch
{
}
what is the problem with background worker my Queue class is like this
class Queue
{
public MsmqMessageFormat ReadMessageFromMSMQ(string queueName)
{
MessageQueue messageQueue = null;
messageQueue = new MessageQueue(@".\Private$\" + queueName);
messageQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(MsmqMessageFormat) });
System.Messaging.Message msg = null;
System.Messaging.Message[] allMessages = messageQueue.GetAllMessages();
if (allMessages.Length > 0)
{
msg = messageQueue.Receive();
MsmqMessageFormat readMessage = (MsmqMessageFormat)(msg.Body);
return readMessage;
}
else
{
return null;
}
}
}
and MsmqMessageFormat class is like this
[Serializable]
public class MsmqMessageFormat
{
public Zvol Zvol { get; set;}
public List<PolicyInterval> listPolicyIntervalInfo = new List<PolicyInterval>();
}
回答1:
Can you clarify on the context of your application?
Is it a Windows Forms app? Console app? Or WPF?
It could have something to do with the apartmentstate of the thread. Threads used by the BackgroundWorker are defaulted to MTA (and you can't override it). While threads created manually could have there apartmentstate set to STA.
回答2:
I'm not sure about your approach is correct.. I would read messages one by one and bind the appropriate events.
From the link:
The Message Loop
The final line in the example above was "queue.BeginReceive()". This is a critical line to a successful implementation of Microsoft Message Queue in that it provides the means for continuous listening on the message queue. Each time a message is received, the listening process stops. This helps provide a thread-safe environment. However, it also means it's the developer's responsibility to resume listening to the queue.
Using the Microsoft Message Queue MSMQ and C#
Also in the last bit of code you have in your question:
if (allMessages.Length > 0)
{
msg = messageQueue.Receive();
MsmqMessageFormat readMessage = (MsmqMessageFormat)(msg.Body);
return readMessage;
}
else
{
return null;
}
This will get all messages and consume them, but will only return the first message even if there are more than one in the queue.
来源:https://stackoverflow.com/questions/4851069/background-worker-thread-problem