【问题标题】:Backgroundworker not busy后台工作人员不忙
【发布时间】:2012-07-15 08:41:56
【问题描述】:

对于一个有点生硬的问题,我很抱歉,可能有几十个答案,但我什至不知道要寻找什么......

我正在使用后台工作人员,但由于某种原因,它似乎并不忙。 在尝试启动工作程序之前,我正在检查它是否很忙。

我里面的代码如下:

    void ClientMsg_BgWrkrTimer_DoWork(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker ClientMsg_BgWrkrTimer = sender as BackgroundWorker;
        string current = msgqueue.Last().Key;
        if (msgqueue.Last().Value.t_Type == 0 || msgqueue.Last().Value.t_Type == 1)
        {
            TimedMsgIcon.Enabled = true;
            foreach (KeyValuePair<string, UUID> g in Msgqueue.Last().Value.t_ngroups)
            {
                GroupNotice ntc = new GroupNotice();
                ntc.Subject = Msgqueue.Last().Value.t_nmsg;
                ntc.Message = Msgqueue.Last().Value.t_nmsg;
                ntc.OwnerID = Client.Self.AgentID;
                UUID key = UUID.Zero;
                if (UUID.TryParse(Msgqueue.Last().Value.t_attach.ToString(), out key))
                {
                    ntc.AttachmentID = key;
                }
                Client.Self.InstantMessage(Client.Self.Name, g.Value, ntc.Subject + "|" 
                    + ntc.Message, UUID.Zero, InstantMessageDialog.GroupNotice,
                    InstantMessageOnline.Online, Vector3.Zero, UUID.Zero,
                    ntc.SerializeAttachment());
                Thread.Sleep(2000);
            }
        }
    }

我已将罪魁祸首缩小为这个:

    Client.Self.InstantMessage(Client.Self.Name, g.Value, ntc.Subject + "|" 
        + ntc.Message, UUID.Zero, InstantMessageDialog.GroupNotice,
        InstantMessageOnline.Online, Vector3.Zero, UUID.Zero,
        ntc.SerializeAttachment());

而且很可能是序列化,就是这个(来自我正在使用的库):

    public struct GroupNotice
    {
        /// <summary></summary>
        public string Subject;
        /// <summary></summary>
        public string Message;
        /// <summary></summary>
        public UUID AttachmentID;
        /// <summary></summary>
        public UUID OwnerID;

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public byte[] SerializeAttachment()
        {
            if (OwnerID == UUID.Zero || AttachmentID == UUID.Zero)
                return Utils.EmptyBytes;

            OpenMetaverse.StructuredData.OSDMap att = new OpenMetaverse.StructuredData.OSDMap();
            att.Add("item_id", OpenMetaverse.StructuredData.OSD.FromUUID(AttachmentID));
            att.Add("owner_id", OpenMetaverse.StructuredData.OSD.FromUUID(OwnerID));

            return OpenMetaverse.StructuredData.OSDParser.SerializeLLSDXmlBytes(att);
        }
    }

问题是,为什么这会阻止我的工人忙碌? 我一拿出来,它就像一个魅力。 不过我需要它,所以我希望任何人都可以帮助我提出问题的原因,以及如何在工作人员中正确使用它。

编辑:

我很抱歉错过了“不工作”的关键点..

所以

“不工作”是指 Client.Self.InstantMessage() 不会启动,后台工作人员也不会忙碌。 如前所述,我在进入工人之前先测试工人是否忙:

    void MsgTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
    {
        if (!ClientSpam_BgWrkrTimer.IsBusy)
        {
            Messagebox.Show("Going into BgWrkr!");
            ClientSpam_BgWrkrTimer.RunWorkerAsync();
        }
    }

使用 Client.Self.InstantMessage() 时,消息框会在每个计时器滴答声中不断弹出,并且工作人员永远不会结束。 但是,如果我删除它,工人就完成了。

【问题讨论】:

  • 如果您帮助读者理解您对“似乎不忙”的定义,可能会提高您获得有用答案的机会。你在测量/测试什么?当你移除罪魁祸首时,测量/测试会如何变化?
  • “工作”是什么意思?你能指望什么?你得到了什么?
  • 减少不必要的细节也会有所帮助,以免读者不知所措。您是否尝试过构建一个简单的测试用例,它不使用 msgqueue(无论该变量是什么类型)、GroupNotice 以及重现您的问题并非绝对必要的任何其他东西?
  • @FrankBoyne 不确定什么应该是不必要的细节。 ://
  • 不必要的细节是任何不会导致错误发生的东西。例如,您发布的代码引用了 msgqueue、TimedMsgIcon 和 GroupNotice,但没有定义它们中的任何一个。您可以显示这些定义,但这会使您的帖子更长,因此更不可能被阅读。创建一个不使用这些变量的测试用例,并且您的帖子变得更具可读性 - 因此更有可能得到答案。同样,您可以通过使用常量值(如 0(或其他)代替 g.Value 和 ntc.Subject 的“测试”)来简化您的 InstantMessage 调用。

标签: c# backgroundworker


【解决方案1】:

我注意到您的工作人员中有 Thread.Sleep(2000) 语句。这将导致工作人员的 .IsBusy 属性在大约 2 秒内为真,加上在 Sleep 之前在方法中花费的任何时间。

您还提到,当出现对 Client.Self.InstantMessage(...) 的呼叫时,工作人员永远不会显得忙。对我来说,这似乎永远不会执行 Thread.Sleep 调用,这意味着 Client.Self.InstantMessage 方法很可能正在引发异常。

尝试将对Client.Self.InstantMessage 的调用封装在try/catch 块中,以查看是否引发了异常。在调试器中运行时,您将能够在 Visual Studio 输出窗口中观察到消息。

        ...

        try
        {    
            Client.Self.InstantMessage(Client.Self.Name, g.Value, ntc.Subject + "|"  
                + ntc.Message, UUID.Zero, InstantMessageDialog.GroupNotice, 
                InstantMessageOnline.Online, Vector3.Zero, UUID.Zero, 
                ntc.SerializeAttachment()); 
        } 
        catch(Exception e)
        {
            Debug.WriteLine("Exception while calling InstantMessage: {0}", e.ToString());
        }

        Thread.Sleep(2000);

        ...

您还可以检查RunWorkerCompletedEventArgs.Error 属性(来自BackgroundWorker.RunWorkerCompleted 事件)以查看工作人员是否引发了异常。

一旦您知道异常是什么,您就能够更好地诊断问题的原因。

【讨论】:

  • 我本可以发誓我大约半小时前评论了这个。但显然不是。非常感谢,我不知道为什么我没有想到在 try/catch 块中捕获错误。我在代码的其他地方使用它。现在我收到了错误消息,只是想弄清楚如何解决它,因为它实际上来自于何时序列化附件。但我最终会到达那里:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
  • 2014-04-14
  • 2016-07-09
  • 1970-01-01
相关资源
最近更新 更多