【问题标题】:Stopping thread does not work停止线程不起作用
【发布时间】:2011-11-07 18:38:52
【问题描述】:

我有一个方法可以监听通过流发送的数据。因为 networkstream.read 方法是同步的,所以我必须在单独的线程上执行它。所以我在一个单独的线程上执行的方法是:

void someMethod(param1, param2....)
{
    try{
     while( stream.read(data...) != 0 )  // code waits here until data is received
     {
        // do stufff

     } 
    }catch{}//
}

我能够退出该线程的唯一方法是关闭流,然后执行 catch 块。我有时需要开始侦听同一流上的数据,但使用不同的方法。因此,如果我将线程创建为 Thread t = new Thread(new threadstart(somemethod......) 然后执行 t.start(someObject); 稍后当我执行 t.abort() 时;该方法仍将监听数据。如何终止它?

我也尝试过创建一个全局变量,例如:

bool someBoolean = false;

void someMethod(param1, param2....)
{
    try{
     while(someBoolean ==false && stream.read(data...) != 0 )  // code waits here until data is received
     {
        // do stufff

     } 
    }catch{}//
}

然后我发现我将 someBoolean 更改为 true,该方法将停止执行。由于某种原因,它没有。为什么?似乎 someBoolean 一次是两个变量。因为从主线程更改它的值似乎不会影响它对第二个线程...

【问题讨论】:

  • 你应该以缓冲的方式从流中读取,意味着同时读取少量数据。显示有关您如何阅读和做事以及线程工作方式的真实代码...
  • stream.Read 将阻塞直到数据可用,因此此时设置布尔值无济于事。

标签: c# multithreading


【解决方案1】:

如何终止它?

解除阻塞流调用的标准协议是关闭流并捕获异常。中断读取只是为了将其移至不同的方法是相当不寻常的。如果您觉得这仍然是必要的,那么您应该在读取操作上提供额外的间接级别。当使用像 BeginRead 这样的异步调用而不是同步调用时,处理这样的场景要容易得多。通过Thread.Abort 终止线程可能会导致比它解决的问题更多的问题。

然后我想我将 someBoolean 更改为 true 方法将停止 执行。由于某种原因,它没有。为什么?好像是一些布尔值 同时是两个变量。因为从主要改变它的价值 线程似乎对第二个线程没有影响...

缺少内存屏障可能会导致此问题,但更可能的原因是线程卡在Read 中,实际上并没有按照您希望的方式读取someBoolean

【讨论】:

    【解决方案2】:

    我猜线程可能被中止,但是来自该线程的资源(由于流而不受管理)将不会被释放 - 那是你的问题。

    不要通过 abort 来停止线程 - 从不。

    请不要尝试使用异步版本的 stream.read 和 CancellationToken。 如果您向我们提供更多信息(什么流?- 读取很奇怪(“R”ead?),线程的开始)我可能会尝试给您更多详细信息。

    PS:尝试使用 System.Threading.Task 代替线程 - 使用起来更好。

    作为没有更多信息的快速修复,您可以尝试以下方法:

    ManualThreadEvent terminate = new ManualThreadEvent(false);
    bool someBoolean = false;
    
    void someMethod(param1, param2....)
    {
        try{
         // wait for enough data or for termination:
         while(terminate.WaitOne(100) == false && stream.DataAvaiable <= bytesNeeded) 
         { /* nothing to do here */ }
    
         if (terminate.WaitOne(0)) return; // terminate on request
    
         // To your stuff with read
        }catch{}//
    }
    
    void Terminate()
    {
      terminate.Set();
    }
    

    【讨论】:

    • 最好创建一个异步版本的 stream.read。 stream 是 NetworkStream 类型,我基本上是在服务器(tcpListener 对象)和客户端之间创建 tcp 连接时创建它。
    • NetworkStream 没问题(只需寻找 BeginRead/EndRead)——但最好给我们可以编译的代码——以上只是片段,很难给你好的建议。正如我所说,使用异步版本并考虑切换到任务 - 如果你使用 CancellationToken-stuff 你应该做得很好。另请注意,您可以使用 .DataAvailable 流检查数据,然后短时间休眠(或短时间等待终止信号)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-10
    • 2019-11-22
    相关资源
    最近更新 更多