在单独的线程中显示MessageBox并自动关闭此线程

时间:2017-02-24 15:10:48

标签: c# wpf multithreading

我使用WPF应用程序和遗留代码。有一种用于分配液体的应用。每次新的剂量应检查杯子是否被分配器更换,如果没有,则显示需要更换杯子的消息。分配器有一个更换杯传感器。如果杯子被更换,我需要自动关闭MessageBox。为此运行两个线程。首先是MessageBox,在另一个调查过程中分配器。这是代码:

public bool CheckChangeCupInThread()
{
    if (_dispenser.Status.CupChanged == DispenserEnums.CupChanged.False)
    {
        var cupFormThread = new ThreadStart(CupWaitChangeForm);
        var cupFormWaiter = new Thread(cupFormThread) {IsBackground = true};
        cupFormWaiter.SetApartmentState(ApartmentState.STA);

        var cupThread = new ThreadStart(WaitForCupChange);
        var cupWaiter = new Thread(cupThread) {IsBackground = true};
        cupWaiter.SetApartmentState(ApartmentState.STA);

        cupFormWaiter.Start();
        cupWaiter.Start();

        do
        {
            //Wait for Cup to be changed or Cancel
        } while (cupFormWaiter.IsAlive && cupWaiter.IsAlive);

        var watch = new Stopwatch();
        watch.Start();

        if (cupFormWaiter.IsAlive)
        {
            cupFormWaiter.Abort();
        }
        if (cupWaiter.IsAlive)
        {
            _dispenser.SurveillanceWorker.Continue = false;
            cupWaiter.Join(200);
            return false;
        }
        watch.Stop();
    }
    return true;
}

private void WaitForCupChange()
{
    do
    {
        _dispenser.GetStatus();
    } while (_dispenser.Status.CupChanged == DispenserEnums.CupChanged.False);
}

private void CupWaitChangeForm()
{
    MessageBox.Show("Change please the cup", "Cup сhange", MessageBoxButtons.Cancel);
}

此代码之前已用于具有超过4000行代码的大型类中。我做了重构并将此代码放在一个单独的类中。现在,更换杯子后程序崩溃,不是在这个地方,而是代码中的某个地方。在Windows 10中使用应用程序时经常会发生的最有趣的事情,这在Windows 7中都不会发生。我是多线程的新手并且无法理解,我该如何解决这个问题。我尝试使用任务和令牌,但令牌不能用MessageBox关闭线程,直到按下按钮。感谢

1 个答案:

答案 0 :(得分:0)

我解决了一个问题。如果Task1完成,现在MessageBox关闭了。或者我关闭MessageBox,然后终止Task1

internal class Program
{
    public const int WM_SYSCOMMAND = 0x0112;
    public const int SC_CLOSE = 0xF060;

    [DllImport("user32.dll")]
    public static extern int FindWindow(string lpClassName, string lpWindowName);

    [DllImport("user32.dll")]
    public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);

    private static void Main(string[] args)
    {
        Action<object> action = (object obj) =>
        {
            int i = 0;
            do
            {
                Thread.Sleep(500);
                i++;
            } while (i < 10);
            Console.WriteLine("t1 has been finished");
        };

        Action<object> action1 = (object obj) =>
        {
            DialogResult result = DialogResult.OK;
            do
            {
                result = MessageBox.Show("This is task2", "Task2", MessageBoxButtons.OKCancel);
            } while (result != DialogResult.Cancel);
            Console.WriteLine("t2 has been finished");
        };

        var tasks = new Task[2];
        var source1 = new CancellationTokenSource();
        var token1 = source1.Token;
        Task t1 = new Task(action, "alpha", token1);
        tasks[0] = t1;
        Task t2 = new Task(action1, "betha");
        tasks[1] = t2;

        t1.Start();
        Console.WriteLine("t1 has been launched. (Main Thread={0})",
            Thread.CurrentThread.ManagedThreadId);

        t2.Start();
        Console.WriteLine("t2 has been launched. (Main Thread={0})",
            Thread.CurrentThread.ManagedThreadId);

        try
        {
            int index = Task.WaitAny(tasks);
            if (t1.Status == TaskStatus.Running)
                source1.Cancel();
            if (t2.Status == TaskStatus.Running)
                CloseMessage();
            Console.WriteLine("Task #{0} completed first.\n", tasks[index].Id);
            Console.WriteLine("Status of all tasks:");
            foreach (var t in tasks)
                Console.WriteLine("   Task #{0}: {1}", t.Id, t.Status);
        }
        catch (AggregateException)
        {
            Console.WriteLine("An exception occurred.");
        }
        Console.ReadLine();
    }

    private static void CloseMessage()
    {
        int window = FindWindow(null, "Task2");
        if (window != 0)
            SendMessage(window, WM_SYSCOMMAND, SC_CLOSE, 0);
    }
}