后台工作线程问题

Posted

技术标签:

【中文标题】后台工作线程问题【英文标题】:Background Worker Thread Problem 【发布时间】:2011-06-18 13:47:40 【问题描述】:

我在我的应用程序中使用后台工作人员

我的代码

 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
    
    
 

我的问题是当我调用这个方法时

 try
 
     message = new Queue().ReadMessageFromMSMQ(server.ServerName);
 
 catch
 
 

在后台工作人员中,我无法调用此方法,只需从 MSMQ 读取消息

但是当我不能使用后台工作者时,只需在这样的简单线程中调用此方法

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

那么这个方法调用正确

try

    message = new Queue().ReadMessageFromMSMQ(server.ServerName);

catch


后台工作人员有什么问题我的队列类是这样的

 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;
         
     
 

而MsmqMessageFormat类是这样的

[Serializable]
public class MsmqMessageFormat
      
    public Zvol Zvol  get; set;
    public List<PolicyInterval> listPolicyIntervalInfo = new List<PolicyInterval>(); 

【问题讨论】:

摆脱那个笨拙的空捕获块,以便您可以诊断问题。如果没有帮助,请发布异常的堆栈跟踪。 您遇到的实际问题是什么。 当我从后台工作人员调用方法时 public MsmqMessageFormat ReadMessageFromMSMQ(string queueName) 这个方法没有被调用 【参考方案1】:

您能说明一下您的应用程序的上下文吗?

它是 Windows 窗体应用程序吗?控制台应用程序?还是 WPF?

这可能与线程的公寓状态有关。 BackgroundWorker 使用的线程默认为 MTA(您不能覆盖它)。虽然手动创建的线程可以将公寓状态设置为 STA。

【讨论】:

实际上是多层应用程序,backgrounworker 进程在我的类库中,我在我的控制台应用程序中添加这个类库引用并从控制台应用程序调用这个进程【参考方案2】:

我不确定你的方法是否正确。我会一一阅读消息并绑定适当的事件。

来自链接:

消息循环

上例中的最后一行 是“queue.BeginReceive()”。这是一个 成功的关键线 微软消息的实现 排队,因为它提供了手段 连续收听 消息队列。每次有消息 收到,监听过程停止。 这有助于提供线程安全的 环境。然而,这也意味着 这是开发商的责任 继续收听队列。

Using the Microsoft Message Queue MSMQ and C#

同样在您的问题中的最后一段代码中:

if (allMessages.Length > 0)
        

            msg = messageQueue.Receive();

            MsmqMessageFormat readMessage = (MsmqMessageFormat)(msg.Body);


            return readMessage;
        
        else
        
            return null;
        

这将获取所有消息并使用它们,但即使队列中有多个消息,也只会返回第一条消息。

【讨论】:

以上是关于后台工作线程问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使后台工作线程之间的事件在自己的上下文中执行

c# - 如何强制关闭运行它自己的线程的后台工作者

在后台线程中删除文件

CoreData 并通知后台工作人员有关主线程的更改

为啥我从后台工作人员调用的委托在主线程中运行

后台工作人员中异步等待中的调解员死锁-如何检测线程调用自身