【问题标题】:I need some help using Threads in C#我需要一些帮助在 C# 中使用线程
【发布时间】:2009-07-04 00:23:45
【问题描述】:

我正在用 C# 开发一个软件,它通过 Wrapper 使用来自 C++ .dll 文件的静态函数。

问题是其中一些函数速度慢且不稳定,所以为了解决这个问题,我创建了一个线程来执行它们。但是,当我从主线程中止该线程时,程序不会让我再次使用这些函数,即使我每次调用函数时都定义了一个新的线程实例。

有什么办法可以解决这个问题吗?

提前致谢。

PS:这是我程序中的一些代码:

public partial class MainForm : Form, IMultiLanguage
{
      //...

      //This method is subscribed to the event of pressing the 'Abort' button
      private void StopCurrentAnalisis()
      {
            try
            {
                this.analisisManagerController.AnalisisThread.Abort();
            }
            catch (Exception e){  }
            finally
            {
                MessageBox.Show("Analisis has been cancelled by user", "Analisis Interrupted", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                CerrarNowLoadingForm();
            }
      }

      //..
}

public class AnalisisManager: IAnalisisManagerController
{
    //..
    private Thread analisisThread;
    public Thread AnalisisThread{get{return this.analisisThread;}}


    public void MakePadrobAnalisis(TipoAnalisis tipoAnalisis,
        Dictionary<string, Dictionary<int, double>> parametros)
    {
        object[] arregloParams = new object[]{tipoAnalisis,parametros};
        analisisThread = new Thread(new ParameterizedThreadStart(MakeAnalisisInOtherThread));
        analisisThread.Start(arregloParams);
    }

 private void MakeAnalisisInOtherThread(object o)
    {
        object[] arregloParams = o as object[];
        TipoAnalisis tipoAnalisis = (TipoAnalisis) arregloParams[0];
        Dictionary<string, Dictionary<int, double>> parametros = arregloParams[1] as Dictionary<string, Dictionary<int, double>>;

        //This launches an event telling the GUI the unstable analisis has started.
        //The method that makes the 'Abort' button to appear on the GUI is subscribed to this event
        StartAnalisis();

       //The Thread executes DLL functions according to tipoAnalisis, for example:
       case InvKinematicsMinTorque:
       {
           WrapperPadirob.InverseKinematicsMinTorqueConfigAnalisis();
           break;
       }
       //..
   }
}

【问题讨论】:

  • 你能发布一些你的代码吗?
  • 真的依赖库...

标签: c# multithreading process


【解决方案1】:

但是,当我中止该线程时 从主线程

那是你的问题。您不应该使用 Thread.Abort。查看this article 中的“非邪恶取消”以获得更好的方法。从那里...

我一直推荐的方法是 死的简单。有一个 volatile bool 对您都可见的字段 工作线程和您的 UI 线程。如果 用户单击取消,设置此标志。 同时,在您的工作线程上,测试 不时升旗。如果你看到 它设置好了,停止你正在做的事情。

另外,在SO thread 中对此进行了很好的讨论。

每条评论:

你拥有这个帖子......

Thread AnalisisThread{get{return this.analisisThread;}}

...它执行一个指向...的委托

private void MakeAnalisisInOtherThread(object o)

...您也拥有该方法。如果 C++ 接口没有合理的 .StopAnalysis 方法(或类似方法),则必须等到分析完成后再轮询主线程,如文章中所述。炸毁您的线程以停止分析是不正确的做法。

【讨论】:

  • 我期待做出这种解决方案,但是如果线程正在执行我无权访问的 C++ 库,我该如何让线程读取布尔值?谢谢
  • @JP,我的回答有什么问题吗?
【解决方案2】:

顺便说一句,您的 C++ dll 是否可以在多个线程中工作?它可能使用仅在仅与一个线程一起使用时才有效的技术。在多个线程中运行它,可能会发生非常糟糕的事情,比如不同的用户访问彼此的数据,或者代码覆盖了 C 运行时库堆。

【讨论】:

    【解决方案3】:

    与其一直创建和杀死线程,不如创建一个运行如下代码的线程:

    private void Worker()
    {
        while (m_bRunning)
        {
    
             m_autoResetEvent.WaitOne();
             DoWork(); // eg. call all required functions, maybe by popping requests off a queue
        }
    }
    

    然后,您可以Set 自动重置事件,该事件将把线程从挂起状态唤醒并让它服务一个请求。

    这还有一个额外的好处,那就是所有调用都将从单个线程对 DLL 进行。

    【讨论】:

      【解决方案4】:

      回顾一下:你有一些非托管代码 那是不稳定的,你需要 从您的 C# 应用程序中消费并且是 寻找最佳消费方式 这个。

      很抱歉,您当前的设计存在缺陷,如果您在线程运行一些任意非托管代码时中止线程,您就有损坏应用程序的风险。 句柄可能泄漏内存可能泄漏,您可能会导致各种难以调试的并发问题

      要解决此类问题,我建议:

      • 最佳解决方案:修复非托管 dll。
      • 次优解决方案:运行一个单独的进程,其唯一职责是与问题 dll 进行交互,如果出现问题,则终止该进程,然后重新启动它。让您的主应用使用远程处理或 WCF 与该进程通信

      【讨论】:

      • 山姆,我同意。额外的间接级别可能足以让该过程完成而不必炸毁它。底线是,你是非常正确的,不客气地炸毁线程是导致无法管理的灾难的秘诀。 :) +1
      【解决方案5】:

      一种允许方法调用因任何原因超时的巧妙方法是使用委托调用。

      [DllImport ("mydll.dll")]
      private extern void method_call ();
      
      private void thing_1 ()
      {
        dll_method_call failing_method;
        IAsycResult method_result;
        Int32 method_timeout;
      
        method_timeout = 15000;
        failing_method = method_call;
        method_result = failing_method.BeginInvoke (null, null);
        if (method_result.AsyncWaitHandle.WaitOne (method_timeout))
        {
          method_result.EndInvoke ();
          //Success
        }
        else
        {
          //Failure
        }
      }
      
      private delegate void dll_method_call ();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-29
        • 2011-03-17
        • 2011-09-26
        • 2013-05-08
        相关资源
        最近更新 更多