如何从另一个范围访问线程?

How do I access a thread from another scope?

这是我遇到问题的代码。我试图停止线程,但我不断收到错误 Use of unassigned local variable 'Listener'。我不明白为什么它未分配。它是在上层范围内定义的。

应该发生的是,在单击 SetMousePos 按钮(绑定到 SetMousePos_Click)时,将弹出一个新的迷你表单,其中包含显示用户鼠标在 (x, y) 坐标。但是,关闭迷你窗体后,它会重新打开,但会挂起并冻结迷你窗体和主窗体。我确定这是因为线程被留下 运行.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DesktopApp1 {
    public partial class Form1 : Form {
        bool KeyPressed = false;

        public Form1() {
            InitializeComponent();

            ClickAmountBox.Value = 0;
            IntervalAmountBox.Value = 0;
        }


        private void SetMousePosBox_Click( object sender, EventArgs e ) {
            MessageBox.Show( "This is a tool to get your mouse's position by simply placing it somewhere. Move your mouse to a position and click the spacebar to record its coordinates. The boxes will autofill the values" );
            


            Form PopUpForm = new Form();
            PopUpForm.Size = new Size( 250, 250 );
            PopUpForm.MaximizeBox = false;
            PopUpForm.MinimizeBox = false;
            PopUpForm.StartPosition = FormStartPosition.CenterScreen;

            Label WaitingLabel = new Forms.Label();
            WaitingLabel.Text = "Waiting for spacebar...";
            WaitingLabel.Size = new Size( 200, 15 );
            WaitingLabel.Location = new Point( 15, 15 );

            Label LabelX = new Forms.Label();
            LabelX.Text = "Mouse X: ";
            LabelX.Location = new Point( 15, 40 );
            LabelX.Size = new Size( 200, 15 );

            Label LabelY = new Forms.Label();
            LabelY.Text = "Mouse Y: ";
            LabelY.Location = new Point( 15, 60 );
            LabelY.Size = new Size( 200, 15 );

            Button OKButton = new Forms.Button();
            OKButton.Location = new Point( 15, 90 );
            OKButton.Text = "OK";
            OKButton.Click += new EventHandler( OkButtonClicked );

            PopUpForm.Controls.Add( WaitingLabel );
            PopUpForm.Controls.Add( OKButton );
            PopUpForm.Controls.Add( LabelX );
            PopUpForm.Controls.Add( LabelY );

            PopUpForm.Show();

            Thread Listener = new Thread( UpdateMouseLocation );

            Listener.Start();

            void UpdateMouseLocation() {
                while( !KeyPressed ) {
                    try {

                        Invoke(
                            new Action(
                                () => {
                                    LabelX.Text = "Mouse X: " + Cursor.Position.X.ToString();
                                    LabelY.Text = "Mouse Y: " + Cursor.Position.Y.ToString();
                                }
                                )
                            );
                    } catch( ObjectDisposedException ) {
                        ;
                    }
                }
            }

            void OkButtonClicked( object sender1, EventArgs e1 ) {
                PopUpForm.Close();

// ============================================================================
// ============================================================================
//  THIS IS THE ERROR LOCATION

                Invoke( new Action( () => {
                    Listener.Abort();
                } ) );
            }
        }
    }
}

如果您在 class 范围内声明 Listener 变量,您的代码应该可以工作。喜欢:

namespace DesktopApp1 {
public partial class Form1 : Form {
    bool KeyPressed = false;
    private Thread Listener = null;

    public Form1() {

并且:

        PopUpForm.Show();

        Listener = new Thread( UpdateMouseLocation );

        Listener.Start();

或者用一个变量来控制执行。这将允许线程干净地结束:

public partial class Form1 : Form
{
    bool KeyPressed = false;
    private Thread Listener = null;
    private bool RunThread = false;

...

        void UpdateMouseLocation()
        {
            RunThread = true;

            while (!KeyPressed && RunThread)
            {
                try
                {

                    Invoke(
                        new Action(
                            () => {
                                LabelX.Text = "Mouse X: " + Cursor.Position.X.ToString();
                                LabelY.Text = "Mouse Y: " + Cursor.Position.Y.ToString();
                            }
                            )
                        );

                    Console.WriteLine(i++);
                }
                catch (ObjectDisposedException)
                {
                    ;
                }
            }
        }

        void OkButtonClicked(object sender1, EventArgs e1)
        {
            PopUpForm.Close();

            // ============================================================================
            // ============================================================================
            //  THIS IS THE ERROR LOCATION

            RunThread = false;
        }