【问题标题】:C#/.NET application design with multi-threading/tasks具有多线程/任务的 C#/.NET 应用程序设计
【发布时间】:2015-04-21 14:18:01
【问题描述】:

我想设计一个应用程序,在两个完全独立的系统之间提供一些双向通信。(桥)
其中一个可以通过 Web 服务调用我的应用程序 - 另一个是第 3 方硬件。它说 RS232。使用 RS232ETH 收发器,我们设法使用 TCP 与硬件进行通信。

该计划具有以下要求

  • 有一个主线程运行“管理服务”。例如,这可能是 WCF 端点或自托管 webapi REST 服务。它提供了启动新工作实例或获取所有工作实例及其各自状态的列表的方法。
  • 有许多“工作”线程。它们每个都有一个包含 5 个状态的状态模型。
  • 例如,在一种状态下,必须生成 TCP 侦听器以接受来自已连接硬件设备的传入连接(基于套接字的编程是强制性的)。一旦它获得所需的信息,它就会发回响应并转换到下一个状态。
  • 应该可以从主(管理器)线程(优雅地)结束单个工作线程(例如,如果工作线程陷入无法恢复的状态)

这就是我的来历:

  • 我考虑过 WCF 工作流服务(状态模型活动),但我不确定如何在那里生成 TcpListener - 并使其保持活动状态。我不需要任何工作流“暂停/序列化和恢复/反序列化”之类的行为。
  • 主线程可能不是什么大问题——它只需要在那里并且运行。让我担心的是子(后台)线程及其内部状态机。
  • 我试图围绕 Tasks 在这里如何提供帮助,但我最终认为线程实际上更适合该任务

由于 .NET (4+) 已经有了很大的发展我不确定要遵循哪种方法...互联网上充斥着 2005 年到 2010 年的示例,这些示例可能超过只是过时了。将 DO 与 DONT 区分开来非常困难。

我很高兴有任何提示。

更新:好的,我会尝试澄清我的问题是什么......

我认为最简单的方法是提供一些伪代码。

public static void Main()
{
    // Start self-hosted WCF service (due to backwards compatibility, otherwise I'd go with katana/owin) on a worker thread
    StartManagementHeadAsBackgroundThread();

    // Stay alive forever
    while(running)
    {
        // not sure what to put here. Maybe Thread.Sleep(500)?
    }

    // Ok, application is shutting down => somehow "running" is not true anymore.
    // One possible reason might be: The management service's "Shutdown()" method is being called
    // Or the windows service is being stopped...

    WaitForAllChildrenToReachFinalState();
}

private static void StartManagementHeadAsBackgroundThread()
{
     ThreadStarter ts = new ThreadStarter(...);
     Thread t = new Thread(ts);
     t.Start();
}

管理负责人(= wcf 服务)提供了一些方法

  • StartCommunicator() 启动新的工作线程以 5 种状态进行实际工作
  • Shutdown() 关闭整个应用程序,让所有工作线程正常完成(通常是几分钟)
  • GetAllCommunicatorInstances() 显示所有工作线程的摘要以及它们所处的当前状态。
  • DestroyCommunicatorInstance(port) 强制结束工作线程 - 例如,如果通信器卡在无法恢复的状态。

无论如何,我需要从“管理”服务(StartCommunicator 方法)生成新的后台线程。

public class Communicator
{
    private MyStateEnum _state;
    public Communicator(int port)
    {
       _state = MyStateEnum.Initializing;
       // do something
       _state = MyStateEnum.Ready;
    }

    public void Run()
    {
        while(true)
        {
             // again a while(true) loop?!
             switch(_state):
             {
                 case MyStateEnum.Ready:
                 {
                     // start TcpListener - wait for TCP packets to arrive.
                     // parse packets. If "OK" set next good state. Otherwise set error state.
                 }
             }

             if(_state == MyStateEnum.Error) Stop();
             break;
        }
    }

    public void Stop()
    {
        // some cleanup.. disposes maybe. Not sure yet.
    }
}

public enum MyStateEnum
{
     Initializing, Ready, WaitForDataFromDevice, SendingDataElsewhere, Done, Error
}

所以问题是我的方法是否能把我带到任何地方,或者我是否完全走错了路。
我如何最好地实现这一点?线程?任务? while(true) 是一个有效的事情吗?如何从我的“管理服务”中与通信器实例交互?我正在寻找的是一种带注释的样板解决方案:)

【问题讨论】:

  • 你有什么问题?

标签: c# .net multithreading workflow state


【解决方案1】:

我的建议是使用 ASP.NET Web API 服务并将控制器操作标记为异步。从那时起,尽可能多地使用任务,当您最终阻塞 IO 时,HTTP 服务器将不会被阻塞。就个人而言,我会避免使用线程,直到您完全确定无法使用任务实现相同的目标。

【讨论】:

    【解决方案2】:

    我建议考虑使用线程池。这将有助于管理资源并更有效地利用资源。

    就终止线程而言,线程池线程是后台工作线程,并且会在您的服务停止时终止,但是,根据您上面的描述,这还不够。您的线程应该始终能够接收要求它们终止的消息。

    【讨论】:

      猜你喜欢
      • 2011-01-14
      • 2017-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-16
      相关资源
      最近更新 更多