我需要一些在 C# 中使用线程的帮助

发布于 2024-07-26 06:58:28 字数 2168 浏览 6 评论 0原文

我正在用 C# 开发一个软件,该软件通过包装器使用 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;
       }
       //..
   }
}

I´m developing a software in C# that uses static functions from a C++ .dll file through a Wrapper.

The problem is that some of these functions are slow and unstable, so in order to solve this I created a Thread that executes them. However, when I abort that thread from the main thread, the program isn´t letting me use those functions again, even though I define a new instance of the thread every time I call a function.

Is there any way I can fix this?

Thanks in advance.

PS: Here is some code from my program:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

山人契 2024-08-02 06:58:28

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

那是你的问题。 您不应该使用 Thread.Abort。 查看这篇文章中的“非邪恶取消” 寻求更好的方法。 从那里 ...

我一直推荐的方法是
太简单了。 有一个不稳定的布尔值
您双方都可以看到的字段
工作线程和你的 UI 线程。 如果
用户单击取消,设置此标志。
同时,在你的工作线程上,测试
时不时举起旗帜。 如果你看到
它已经设置好了,停止你正在做的事情。

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

根据评论:

您拥有这个线程……

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

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

private void MakeAnalisisInOtherThread(object o)

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

However, when I abort that thread
from the main thread

That's your problem. You should not be using Thread.Abort. Check out "Non-Evil Cancellation" in this article for a better approach. From there ...

The approach I always recommend is
dead simple. Have a volatile bool
field that is visible both to your
worker thread and your UI thread. If
the user clicks cancel, set this flag.
Meanwhile, on your worker thread, test
the flag from time to time. If you see
it get set, stop what you're doing.

Also, very good discussion of this in this SO thread.

Per comment:

You own this thread ...

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

... it executes a delegate pointing to ...

private void MakeAnalisisInOtherThread(object o)

... you also own that method. If the C++ interface does not have a reasonable .StopAnalysis method (or something similar), you must wait until the analysis is done and then poll the main thread as discussed in the articles. Blowing up your thread to stop the analysis is not the right thing to do.

我还不会笑 2024-08-02 06:58:28

顺便说一句,你的 C++ dll 是为在多线程中工作而编写的吗? 它可能使用仅在仅与一个线程一起使用时才有效的技术。 在多个线程中运行它,可能会发生非常令人讨厌的事情,例如不同的用户访问彼此的数据,或者代码覆盖 C 运行时库堆。

BTW, is your C++ dll written to work in multiple threads? It's possible that it uses techniques that only work when it's being used with only one thread. Run it in multiple threads, and very nasty things could happen, like different users accessing each others data, or the code overwriting the C runtime library heap.

埋葬我深情 2024-08-02 06:58:28

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

private void Worker()
{
    while (m_bRunning)
    {

         m_autoResetEvent.WaitOne();
         DoWork(); // eg. call all required functions, maybe by popping requests off a queue
    }
}

然后,您可以设置自动重置事件,该事件会将线程从挂起状态唤醒并为其提供服务一个请求。

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

Rather than creating and killing threads all the time, it's better to create one thread which runs code like this:

private void Worker()
{
    while (m_bRunning)
    {

         m_autoResetEvent.WaitOne();
         DoWork(); // eg. call all required functions, maybe by popping requests off a queue
    }
}

Then, you can Set the auto-reset event which will wake the thread from suspend and have it service one request.

This has the additional benefit that all calls will be made to the DLL from a single thread.

旧故 2024-08-02 06:58:28

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

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

为了解决此类问题,我建议:

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

To recap: you have some unmanaged code
that is unstable, which you need to
consume from your C# app and are
looking for the best way to consume
this.

Sorry to say this, but your current design is flawed, if you abort a thread while its running some arbitrary unmanaged code you are risking corrupting your application. Handles can leak, memory can leak, you can cause all sorts of incredibly hard to debug concurrency issues.

To solve this kind of problem I would recommend:

  • Best solution: get the unmanaged dll fixed.
  • Second best solution: run a separate process whose sole responsability is to interact with the problem dll, if stuff plays up, terminate the process and then start it up again. Have your main app communicate with that process using remoting or WCF
丑疤怪 2024-08-02 06:58:28

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

[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 ();

A slick way to allow a method call to timeout for whatever reason is to use a delegate call.

[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 ();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文