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

Windows 10 LTSB和C#Winforms-线程问题,c#,multithreading,windows-10,C#,Multithreading,Windows 10,所以我这里的问题很简单。我设计了一个WinForms应用程序,它在我的机器(Win7)和其他机器上运行得很好,但当我在Windows 10 2016 LTSB机器上运行该应用程序时,我的后台线程并不像预期的那样工作,但有些线程的性能确实如预期的那样 申请流程: 等待1分钟(带线程计时器的obj1) Post事件(当主窗口调用obj1时来自obj1的字符串消息) 更新表单文本(带有来自事件消息的信息) 执行操作(后台线程) 发布事件消息(从后台线程到主窗口) 等待随机周期(带线程计时器的obj1

所以我这里的问题很简单。我设计了一个WinForms应用程序,它在我的机器(Win7)和其他机器上运行得很好,但当我在Windows 10 2016 LTSB机器上运行该应用程序时,我的后台线程并不像预期的那样工作,但有些线程的性能确实如预期的那样

申请流程:

  • 等待1分钟(带线程计时器的obj1)
  • Post事件(当主窗口调用obj1时来自obj1的字符串消息)
  • 更新表单文本(带有来自事件消息的信息)
  • 执行操作(后台线程)
  • 发布事件消息(从后台线程到主窗口)
  • 等待随机周期(带线程计时器的obj1)
  • Post事件(来自obj1的字符串消息)
  • 更新表格
  • 等一分钟
现在,由于一些隐私政策/原因,我无法分享此处操作的确切内容以及类的结构,但这里是一个基本的类结构:

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;
        }
    }
}

我要结束这个问题,因为这完全是废话,我为他们花在阅读这篇文章上的时间向他们道歉

因此,
队列
上的手动锁以前一直导致死锁,因此它们被移除。现在,它一开始似乎解决了这个问题,但长时间运行的测试证明,时不时(我认为是Windows问题)会出现死锁

我之所以认为这是Windows的问题,是因为有人告诉我,这是他们在Windows上的体验,这肯定是Windows的问题。没有看不起任何人,但他不做线程,因为他不知道如何做,提到的结果是他试图做线程。从这里吸取的教训

谢谢各位

编辑:
问题已经解决,长期运行的测试到目前为止看起来非常有希望。为了实现这一点,我只需将
Queue
更改为
ConcurrentQueue
,并在需要的地方对代码进行一些修改(即
ConcurrentQueue.Clear()
不存在于
Queue.Clear()
存在的地方)。

让你的应用程序生成日志文件,然后在所有必要的地方添加日志条目。通过阅读和比较日志文件,您应该能够了解可能的错误。一种更快的方法是实时调试,但不确定是否允许直接在Windows 10机器上工作。请考虑方法。然后可以将代码简化两次。还要将.NET版本目标至少更新到4.6。有关TPL的更多信息:手动实现的状态机可以替换为简单的线性
async
方法。As
async/await
实现状态机本身。异步编程现在在C#中尽可能简单。请注意太旧的代码。您好@aepot,我将快速查看TPL谢谢。至于“状态机”,有一个物理外部设备,我正在模拟它来为应用程序提供测试运行。原始代码实际上与一个串行端口通信,该设备是一个128Kb的ARM处理器。我不允许更改设备,只能更改调节设备的应用程序。谢谢您的时间。@aepot,我正在使用NET4.7.2。目前我认为我发现了问题。我将队列更改为ConcurrentQueue。我在队列上有手动锁,但我以前删除过这些锁,以删除排队/出列事件处理程序上发生的死锁。我想一些我没有记录的东西悄无声息地死掉了——尽管如此,仍然在测试。现在有一个不同的问题,我将不得不通过
CreateProcessAsUser
advapi32.dll
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();