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# 当用户单击“终止运行线程”;X";表单上的按钮_C#_Multithreading_Events_Formclosing - Fatal编程技术网

C# 当用户单击“终止运行线程”;X";表单上的按钮

C# 当用户单击“终止运行线程”;X";表单上的按钮,c#,multithreading,events,formclosing,C#,Multithreading,Events,Formclosing,假设我有一个名为mainFrm的表单和一个名为objectA的对象,该对象保存正在运行的线程。当这两种情况发生时,我的程序应关闭: (1)。用户单击mainFrm中的“X”按钮(因此mainFrm.FormClosing被触发) (2)。在objectA中引发了一个事件(我们将其命名为“connectionClosed”) 因此,无论触发(1)或(2),此事件链始终应包括: 底层线程中任何对象的终止。)我已经知道怎么做了 使用位于objectA中的代码优雅地终止它们) 当然,mainFrm要关门

假设我有一个名为mainFrm的表单和一个名为objectA的对象,该对象保存正在运行的线程。当这两种情况发生时,我的程序应关闭:

(1)。用户单击mainFrm中的“X”按钮(因此mainFrm.FormClosing被触发)

(2)。在objectA中引发了一个事件(我们将其命名为“connectionClosed”)

因此,无论触发(1)(2),此事件链始终应包括:

  • 底层线程中任何对象的终止。)我已经知道怎么做了 使用位于objectA中的代码优雅地终止它们)
  • 当然,mainFrm要关门了
  • 解决这个问题的最好办法是什么

    我就是这样解决的

    不知道为什么这个问题没有得到社区的好评。我认为这是相当清楚和直截了当的。下面是我如何解决它的,我希望这也有助于更好地定义我的意思。如果您还有其他疑问,请告诉我=)

    在form类中:

    ...
    this.FormClosed += objectA.kill;
    objectA.connectionClosed +=closeForm;
    ...
    
    private void closeForm(object sender, FormClosedEventArgs e)
    {
        try
        {
            this.Invoke(new MethodInvoker(delegate { this.Close(); }));
        }
        catch { }
    }
    
    在objectA的类中:

    ...
    //connectionClosed is raised in different parts of objectA's   threads code
    connectionClosed += killClient; 
    ...
    
    public void killClient(object sender, FormClosedEventArgs e)
    {
        //event should go past this point just once
        if (!_connectionClosed)
        {
            _connectionClosed = true;
    
            try
            {
                ... //close connection killing all threads
            }
            catch { }
        }
    }
    
    根据(1)和(2)开头陈述的用例,这就是应该发生的事情(如果我没有弄错的话)

    (1)。用户单击“X”按钮->表单关闭->表单关闭被引发->objectA.kill方法委托被执行->内部线程引发一些connectionClosed事件,这些事件将触发更多objectA.kill执行,但由于易失性bool\u connectionClosed,这不会造成任何损害(当然,因为有一个try/catch无论如何都会起作用,但对我来说,不要再执行这样的代码更有意义)->线程被objectA.kill->SUCCESS的唯一完整执行终止

    (2).服务器关闭连接或网络错误->objectA的内部线程检测到连接错误并引发多个connectionClosed事件->不同的线程将尝试执行objectA.kill方法委托。->同时,在主窗体中执行closeForm,关闭窗体->这也会触发另一个objectA.kill执行(感谢this.FormClosed+=\u client.killClient;)->同样,这不会造成任何伤害,因为_connectionclosedvolatile bool将只允许一个线程实际执行代码(引发事件的第一个线程)->只有完全执行objectA.kill->SUCCESS才能正常终止线程


    下一步应该是找到一种更方便的方法,这样connectionClosed可能只上升一次,我现在就用谷歌搜索它=)

    调用Close()有什么问题关于事件?如果您在FormClose上切换布尔值,则可以忽略下一个事件。如果您想在关闭窗体之前中断用户操作,则仅使用FormClosing。使用FormClosing可以阻止关闭论坛。如果某些数据未保存,并且您询问用户是否希望使用您关闭窗体,则通常使用此选项t保存,否则取消关闭


    因此,不要使用FormClosing,使用FormClosing来清理实例。

    我不确定这是否能帮助您解决问题,但您应该参考以下代码。 这是一个使用线程对象来改变表单颜色的例子。当事件<代码>对象Objuta时,<代码>窗体<代码>自动关闭。DoMoOthOuts<代码>提高了20倍(<代码>如果(计数> 20):你可以考虑这个动作,就像你的事件连接被关闭了一样)。;或者您可以在线程运行时随时通过单击
    Form1
    的“X”按钮关闭
    Form1

    public delegate void ObjectADoSomethingEventHandler(object sender, ObjectADoSomethingEventArgs e);
    public class ObjectADoSomethingEventArgs : EventArgs
    {
        public int Value { get; private set; }
        public ObjectADoSomethingEventArgs(int value)
        {
            Value = value;
        }
    }
    
    
    public class ObjectA
    {
        public event ObjectADoSomethingEventHandler DoSomething;
        protected void OnDoSomething(int value)
        {
            if (DoSomething != null)
                DoSomething(this, new ObjectADoSomethingEventArgs(value));
        }
    
        public event EventHandler Closed;
        protected void OnClosed()
        {
            if (Closed != null)
                Closed(this, new EventArgs());
        }
    
    
        private BackgroundWorker _worker;
        public ObjectA()
        {
            _worker = new BackgroundWorker();
            _worker.DoWork += new DoWorkEventHandler(_objectA_DoWork);
            _worker.ProgressChanged += new ProgressChangedEventHandler(_objectA_ProgressChanged);
            _worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_objectA_RunWorkerCompleted);
            _worker.WorkerReportsProgress = true;
            _worker.WorkerSupportsCancellation = true;
        }
    
        public void Start()
        {
            _worker.RunWorkerAsync();
        }
    
        public void Kill()
        {
            if (_worker != null && _worker.IsBusy)
            {
                _worker.CancelAsync();
            }
        }
    
        private void _objectA_DoWork(object sender, DoWorkEventArgs e)
        {
            int count = 0;
            while (true)
            {
                _worker.ReportProgress(count);
                count++;
                if (count > 20)
                {
                    return; // exit thread.
                }
    
                if (_worker.CancellationPending)
                {
                    e.Cancel = true;
                    return; // Thread cancelled.
                }
                Thread.Sleep(500);
            }
        }
    
        private void _objectA_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            OnDoSomething(e.ProgressPercentage);
        }
    
        private void _objectA_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            OnClosed();
        }
    }
    
    
    public partial class Form1 : Form
    {
        private ObjectA _objectA;
    
        public Form1()
        {
            InitializeComponent();
            _objectA = new ObjectA();
            _objectA.DoSomething += _objectA_DoSomething;
            _objectA.Closed += _objectA_Closed;
            _objectA.Start();
        }
    
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            _objectA.Kill();
        }
    
        private int _red = 128;
        private int _green = 128;
        private int _blue = 128;
        void _objectA_DoSomething(object sender, ObjectADoSomethingEventArgs e)
        {
            _red += 15;
            if (_red > 255) _red = 128;
            _green -= 15;
            if (_green < 0) _green = 128;
            _blue += 15;
            if (_blue > 255) _blue = 128;
            this.BackColor = Color.FromArgb(_red, _green, _blue);
            this.Text = string.Format("Count = {0}", e.Value);
        }
    
        void _objectA_Closed(object sender, EventArgs e)
        {
            Close();
        }
    }
    
    public委托void ObjectADoSomethingEventHandler(对象发送方,ObjectADoSomethingEventArgs e);
    公共类ObjectADoSomethingEventArgs:EventArgs
    {
    公共int值{get;private set;}
    公共对象ADOSomethingEventArgs(int值)
    {
    价值=价值;
    }
    }
    公共类对象
    {
    公共事件反对某些事情,甚至反对某些事情;
    受保护的void OnDoSomething(int值)
    {
    if(DoSomething!=null)
    DoSomething(此,新对象adosomethingeventargs(值));
    }
    公共事件处理程序关闭;
    受保护的void OnClosed()
    {
    如果(关闭!=null)
    已关闭(此为新的EventArgs());
    }
    私人背景工人;
    公众反对a()
    {
    _worker=新的BackgroundWorker();
    _worker.DoWork+=新的doworkenventhandler(\u objectA\u DoWork);
    _worker.ProgressChanged+=新的ProgressChangedEventHandler(\u objectA\u ProgressChanged);
    _worker.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(\u objectA\u RunWorkerCompleted);
    _worker.WorkerReportsProgress=true;
    _worker.worker支持扫描单元=true;
    }
    公开作废开始()
    {
    _worker.RunWorkerAsync();
    }
    公共空杀()
    {
    if(_-worker!=null&&u-worker.IsBusy)
    {
    _worker.CancelAsync();
    }
    }
    私有void\u objectA\u DoWork(对象发送方,DoWorkEventArgs e)
    {
    整数计数=0;
    while(true)
    {
    _工人。报告进度(计数);
    计数++;
    如果(计数>20)
    {
    return;//退出线程。
    }
    如果(_worker.CancellationPending)
    {
    e、 取消=真;
    return;//线程已取消。
    }
    睡眠(500);
    }
    }
    私有void\u objectA\u ProgressChanged(对象发送方,progresschangedventargs e)
    {
    OnDoSomething(如百分比);
    }
    私有void\u objectA\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
    {
    OnClosed();
    }
    }
    公共部分类Form1:Form
    {
    私人反对a_反对a;
    公共表格1()
    {
    初始化组件();
    _objectA=新的objectA();
    _objectA.DoSomething+=\u objectA\u DoSomething;
    _objectA.Closed+=\u objectA\u Closed;
    _objectA.Start();