繁体   English   中英

Windows 10 LTSB 和 C# Winforms - 线程问题

[英]Windows 10 LTSB and C# Winforms - Threading Issue

所以我这里的问题很简单。 我设计了一个 WinForms 应用程序,它在我的机器 (Win7) 上运行良好,实际上在其他机器上运行良好,但是当我在 Windows 10 2016 LTSB 机器上运行该应用程序时,我的后台线程无法按预期工作 - 但有些线程可以按预期执行。

申请流程:

  • 等待 1 分钟(带有 Threading.Timer 的 obj1)
  • 发布事件(当 MainWindow 调用 obj1 时来自 obj1 的字符串消息)
  • 更新表单文本(使用事件消息中的信息)
  • 执行操作(后台线程)
  • 发布事件消息(从后台线程到主窗口)
  • 等待随机周期(带有 Threading.Timer 的 obj1)
  • 发布事件(来自 obj1 的字符串消息)
  • 更新表格
  • 等待 1 分钟

现在出于某些隐私政策/原因,我无法分享此处操作的确切内容以及类的结构,但这是一个基本的 class 结构:

class MainWindow
{
    List<Controller> controllers = new List<Controller>();
    List<ControllerDisplay> controllerDisplays = new List<ControllerDisplay>();
    Queue<string> requests = new Queue<string>();
    
    private void AppLifetimeLoopCallback(object state)
    {
        while (requests.Count > 0)
        {
            string request = requests.Dequeue();
            string response = controllers[i].ProcessRequest(request);
            string anotherResponse = controllerDisplays[i].ProcessResponse(response);
            if (!string.NullOrWhiteSpace(anotherResponse))
            {
                requests.Enqueue(anotherResponse);
            }
        }
        
        for (int i = 0; i < controllers.Count; i++)
        {
            requests.Enqueue("STATE?");
        }
        
        timer.Change(300, Threading.Timeout.Infinite);
    }
}

class Controller
{
    public string ProcessRequest(string request)
    {
        switch (request)
        {
            case "STATE?":
              if (shouldRequest)
              {
                  return "REQ:1234";
              }
              else if (isProcessing)
              {
                  return "PRQ:1234";
              }
              else
              {
                  return "IDLE";
              }
              
              break;

            case "APPROVE":
              shouldRequest = false;
              isProcessing = true;
              thread = new Threading.Thread(new ThreadStart(() =>
              {
                  Threading.Thread.Sleep(300);
                  isProcessing = false;
                  return "RQF:1234";
              })
              {
                  IsBackground = true,
              };
              thread.Start();
              
              break;

            case "DENY:
              shouldRequest = false;
              break;
        }
    }
}

class ControllerDisplay
{
    public string ProcessResponse(string response)
    {
        switch (request.Substring(0, 4))
        {
            case "REQ:":
              thread = new Threading.Thread(new ThreadStart(() => 
              {
                  // perform some checks
                  if (isValid)
                  {
                     return "APPROVE";
                  }
                  else
                  {
                      return "DENY";
                  }
              })
              {
                  IsBackground = true,
              };
              thread.Start();
              
              break;

            case "RQF:":
              thread = new Threading.Thread(new ThreadStart(() =>
              {
                  // finalize and cleanup request bits
                  return "APPROVE";
              })
              {
                  IsBackground = true,
              };
              thread.Start();
              
              break;

            case "PRQ:":
              // update UI
              break;
        }
    }
}

现在首先,我知道代码中的毫秒延迟与流程描述之间似乎存在一些差异 - 但是请注意Controller中还有另一个Thread以这一分钟的间隔切换shouldRequest值,从而切换响应消息在请求设备的 state 时执行“请求”。

其次,我还注册了应用程序的UnhandledExceptionThreadException事件,这些事件应记录发生的任何不良行为。

第三,请注意,在 MainWindow 中有一个Threading.Timer (不在代码中 - 我知道)每秒用当前日期和时间更新 UI。

现在我注意到的问题是,在 Win10LTSB2016 机器上,应用程序停止执行后台操作。 一些线程一定是刚死掉,或者日期和时间按预期不断更新,但是一个 controller 将卡在请求 state 中,另一个在请求完成 state 中 - 并且没有记录错误消息/ MessageBox 请注意,机器不会 go 进入任何睡眠或 hibernate state 在此期间线程刚刚停止,另一个注意是 memory sockets 是 1,而不是 2(因为我读到这可能会影响线程彼此失去通信如果它们被划分到不同的处理器组并且您的应用程序未编写来处理这个问题)。

关闭:请注意,当我执行检查以查看是否应该在Controller class 中启动请求进程线程时,以便在检测到 state 更改之前不会一遍又一遍地执行相同的请求,我执行以下操作:

lock (checkLock)
{
    if (isProcessingRequest)
    {
        break;
    }
    else
    {
        lock (resourceLock)
        {
            isProcessingRequest = true;
        }
    }
}

thread = new Threading.Thread(new ThreadStart(() =>
{
    lock (resourceLock)
    {
        // finalize and cleanup request bits
        isProcessingRequest = false;
    }
    
    return "APPROVE";
})
{
    IsBackground = true,
};
thread.Start();

我要结束这个问题,因为它完全是胡说八道,我向那些花时间阅读这篇文章的人道歉。

所以Queue<T>上的手动锁之前一直导致死锁,因此它们被删除了。 现在它似乎首先解决了问题,但是长时间运行的测试时不时地证明(我认为是 Windows 问题)发生了死锁。

我之所以认为这是一个 Windows 问题,是因为有人告诉我这是他们在 Windows 上遇到的情况,这绝对是一个 Windows 问题。 不看不起任何人,但他不做线程,因为他不知道如何做,并且提到的结果是他尝试做线程。 在这里吸取教训。

谢谢伙计们和/或姑娘们。

编辑:问题已解决,到目前为止,长时间运行的测试看起来很有希望。 为实现这一点,我只是将Queue<T>更改为ConcurrentQueue<T>并在需要时对代码进行了一些修改(即ConcurrentQueue<T>.Clear()不存在,而Queue<T>.Clear()存在)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM