gpt4 book ai didi

c# - WinForms UI 有时无响应

转载 作者:太空宇宙 更新时间:2023-11-03 21:43:52 25 4
gpt4 key购买 nike

我正在更新与 GSM 调制解调器通信的 WinForms 应用程序,简而言之,执行以下功能:

  • 接受传入的 SMS 消息并将它们上传到基于 SOAP 的网络服务
  • 从基于 SOAP 的网络服务下载消息,将它们转换为 SMS 消息并将它们发送到目标地址

这个功能是这样划分的:

  1. 处理传入 SMS 消息的代码是 GSM 库的一部分。它被设置为一个事件处理程序,当调制解调器接收到新的传入消息时触发。事件处理程序只是将消息转换为特定的字符串格式(源电话号码、消息正文)并将其添加到队列中以上传到 Web 服务。

  2. 将消息上传到 Web 服务的代码作为任务运行,该任务由间隔为 15 秒的计时器启动。此代码只是使所有 SMS 消息出列,将它们上传到 Web 服务,更新 UI 中的标签以指示队列中没有剩余消息,然后终止。

  3. 从 Web 服务下载消息的代码也作为任务运行,它也由间隔为 15 秒的计时器触发。它只是从 Web 服务下载任何新消息,将它们添加到固定大小的“传出”队列,更新 UI 中的标签以指示队列中的消息数量,然后终止。

  4. 最后,构建和发送队列中传出 SMS 消息的代码作为任务运行。此代码在一个相当紧凑的循环中运行,当传出队列中有任何消息时,该循环会不断发送消息。此代码还会在从队列中删除消息并将其发送到目标电话号码后更新 UI 中的标签。

回顾一下,上面的第 2、3 和 4 项作为任务运行。我将相同的取消 token 传递到每个任务中,因此如果用户关闭我的应用程序,我可以取消它们。一切似乎都按预期工作,除了以下情况:如果 GSM 调制解调器正在运行但我的应用程序没有运行,传入的 SMS 消息将存储在 SIM 卡上,直到它已满(在本例中为 30 条消息),然后,它们将开始在 SMSC 排队。当我的应用程序启动时,我检查存储在 SIM 上的消息并处理它们。如果 SIM 已满,一旦我开始处理和删除这些消息,任何在 SMSC 排队的消息都将开始传送。正是在这一点上,有时我的用户界面会卡住。我基本上有三段代码来进行 UI 更新,它们被我上面描述的各种任务调用:

    // update the status textbox (a multi-line textbox)
private void UpdateStatusText(string text)
{
textBoxStatus.BeginInvoke((MethodInvoker)delegate { textBoxStatus.AppendText(text + Environment.NewLine); });
}

// update UI with the current number of messages in the incoming queue
private void UpdateIncomingMessageQueueCount()
{
labelIncomingQueueCounter.BeginInvoke((MethodInvoker)delegate { labelIncomingQueueCounter.Text = messagesFromDevicesQueue.GetCount().ToString(); });
}

// update the UI with the current number of messages in the outgoing queue
private void UpdateOutgoingMessageQueueCount()
{
labelOutgoingQueueCounter.BeginInvoke((MethodInvoker)delegate { labelOutgoingQueueCounter.Text = messagesToDevicesQueue.GetCount().ToString(); });
}

我不完全确定是什么导致了卡住,但是当它发生并且我能够在调试器中中断时,我可以看到一些状态为“已阻止”的任务并且悬停在提示上说“没有可用的等待信息”。正如我之前所说,这似乎只有在有大量传入消息时才会发生。在那种情况下,我将调用 UpdateIncomingMessageQueueCount() 相当数量(在每个传入消息排队之后)。对于 UpdateIncomingMessageQueueCount(),它通过 queues.GetCount() 方法获取队列中的消息数。固定大小的队列对象是这样实现的:

public class FixedSizeQueue<T>
{

private readonly List<T> queue = new List<T>();
private readonly object syncObj = new object();

public int Size { get; private set; }

public FixedSizeQueue(int size)
{
Size = size;
}

public void Enqueue(T obj)
{
lock (syncObj)
{
queue.Insert(0, obj);

if (queue.Count > Size)
{
queue.RemoveRange(Size, queue.Count - Size);
}
}
}

public T[] DequeueAllItems()
{
lock (syncObj)
{
var result = queue.ToArray();
queue.Clear();
return result;
}
}

public void RemoveFirstItem()
{
lock (syncObj)
{
if (queue.Count > 0)
{
queue.RemoveAt(0);
}
}
}

public T Peek()
{
lock (syncObj)
{
if (queue.Count > 0)
{
var result = queue[0];
return result;
}
else
{
return default(T);
}
}
}

public void Flush()
{
lock (syncObj)
{
queue.Clear();
}
}

public int GetCount()
{
lock (syncObj)
{
return queue.Count;
}
}
}

由于我使用 .BeginInvoke() 来更新 UI,我想知道我的性能问题是否与对队列对象调用 .GetCount() 的大量异步尝试有关? UI 最终会再次响应,但这显然不应该发生。

最佳答案

您正在为传入的每条消息调用 BeginInvoke。这最终导致将一大堆接连发生的 UI 更新排队,有效地阻塞了 UI 线程。

最好为每条消息调用 Invoke。或者,更好的是,更改您的设计,以便您清空队列并一次性更新所有消息的单个 UI。

关于c# - WinForms UI 有时无响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18024747/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com