Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 手动复位事件不工作;线_C#_Multithreading_Wcf_Manualresetevent - Fatal编程技术网

C# 手动复位事件不工作;线

C# 手动复位事件不工作;线,c#,multithreading,wcf,manualresetevent,C#,Multithreading,Wcf,Manualresetevent,我有一个创建线程的客户端 该线程有一个WaitOne(),因此,当它卡在那里时,我的客户端不会死掉。 但是,当我想关闭客户端时,我需要对手动重置事件执行Set() 我在主类中声明手动重置事件: public ManualResetEvent mreIn = new ManualResetEvent(false); 这是我的Connect函数,它使用start函数创建线程: public void Connect() { objClientThread = new

我有一个创建线程的客户端

该线程有一个
WaitOne()
,因此,当它卡在那里时,我的客户端不会死掉。 但是,当我想关闭客户端时,我需要对手动重置事件执行
Set()

我在主类中声明手动重置事件:

public ManualResetEvent mreIn = new ManualResetEvent(false);
这是我的
Connect
函数,它使用start函数创建线程:

    public void Connect()
    {
        objClientThread = new Thread(start) { IsBackground = true };
        objClientThread.Start();
    }

    /// <summary>
    /// Starts the client program.
    /// </summary>
    private void start()
    {
            //We Open the proxy to let connections happen
            objProxy.Open();
            if (performHandshake())
            {
                IsConnected = true;
                DelayedShutdownBool = false;
                //While connected, the thread keeps the client alive
                mreIn.WaitOne();
                if (OnShutdownInitiated != null)
                {
                    OnShutdownInitiated(this, new EventArgs());
                }
                System.Threading.Thread.Sleep(500);
                objProxy.Close();
                objConfiguration = null;
                IsConnected = false;
                mreOut.Set();
            }
        }
因此,这种方法的工作原理是。。。 所有模块都在
WaitOne()上初始化和阻止
当我关闭一个模块时,回调函数执行
Set()
,但是
WaitOne()
没有解锁,线程也不会继续。
我遗漏了什么?

看起来您使用ManualResetEvent的方式是正确的。但是,您的线程是背景。如果所有其他非后台线程都退出,那么您的线程将在随机位置中止,并且
mreIn.WaitOne()之后的代码可能不会执行


如果是这样的话,那么将您的therad设置为非后台将解决问题。

问题是,当我创建服务客户端时,我必须传递回调的instance上下文,并且我正在执行一个新的
操作,因此我没有将
当前的
实例上下文放入,而回调正在对其他实例执行,因此,我所做的每一个价值观或事件的变化都没有反映在当前的价值观中。

感谢@Henkholtman的帮助:)

请注意以下示例:

class ThreadManager : IThreadManager
{
    private System.Threading.ManualResetEvent _Mre;
    private static CancellationTokenSource _CancellationToken;
    private int _ThreadCount;

    public ThreadManager(int threadCount)
    {
        _Mre = new System.Threading.ManualResetEvent(true);
        _CancellationToken = new CancellationTokenSource();
        _ThreadCount = threadCount;
    }

    public void DoWork(Action action)
    {
        _Mre.WaitOne();
        Task.Factory.StartNew(action, _CancellationToken.Token);
    }

    public void Stop()
    {
        _CancellationToken.Cancel();
    }

    public void Resume()
    {
        _Mre.Set();
    }

    public void Waite()
    {
        _Mre.Reset();
    }
}

第一个检查:回调是否在同一个实例上运行?是的,回调运行同一个实例。客户端是使用executeAssembly执行的
.exe
。此
.exe
具有客户端类的实例。当
exe
启动时,调用
Connect()
函数,创建线程,但您的objProxy看起来像一个命名错误的主机。objProxy被配置为访问端点并具有配置,以便netNamedPipes可以找到服务器。与此无关我做了更多的测试,看起来回调中执行的任何操作都不会执行,就像其他对象一样。如何确保回调是在同一对象上执行的?此后台线程使用eventhandler控制其他线程。另一条线肯定没有死,100%肯定
class ThreadManager : IThreadManager
{
    private System.Threading.ManualResetEvent _Mre;
    private static CancellationTokenSource _CancellationToken;
    private int _ThreadCount;

    public ThreadManager(int threadCount)
    {
        _Mre = new System.Threading.ManualResetEvent(true);
        _CancellationToken = new CancellationTokenSource();
        _ThreadCount = threadCount;
    }

    public void DoWork(Action action)
    {
        _Mre.WaitOne();
        Task.Factory.StartNew(action, _CancellationToken.Token);
    }

    public void Stop()
    {
        _CancellationToken.Cancel();
    }

    public void Resume()
    {
        _Mre.Set();
    }

    public void Waite()
    {
        _Mre.Reset();
    }
}