简单等待后台进程结束C#

时间:2018-05-26 09:33:20

标签: c# .net

我有这个(可能是微不足道的问题)。我在表格上移动卡片,在一个过程中我需要等待,直到卡片完成移动(并添加到CardDeck类中)。出于课堂设计的原因,我无法将卡片添加到新的Deck中。我需要的是等待继续代码在计时器上的几个刻度(在后台运行)。我在Stackoverflow上找到了等待例程,但它在这种情况下运行并且在使用Process时丢失了。有没有简单的方法等待几毫秒,而程序仍在运行(计时器滴答,卡片在每个滴答上移动)。我不确定这是否可以在没有线程的情况下完成,但我希望它是。

private void buCompW1W2_Click(object sender, EventArgs e) {
        //starts moving card to new position
        DeckPOne.MoveCardFromTopToTop(WarPOne);
        DeckPTwo.MoveCardFromTopToTop(WarPTwo);
        //code I hope to enter to delay next steps
        Stopwatch stopwatch = Stopwatch.StartNew();
        while (true) { //AwaitingReceiving indicates is Deck expects to receive card, 0 means, card is already there
            if (WarPOne.AwaitingRecieving == 0 && WarPTwo.AwaitingRecieving == 0)
                break;
        }
        //this test must be done after cards arrive to new place, else its error (-1)
        //test compares cards in WarPOne and WarPTwo, but cards are not there yet (cards are waiting for timer tick to change position etc.) so it returns
        //en error, mechanicaly done it works like intended
        switch (CompareCards(WarPOne.TopCard, WarPTwo.TopCard)) {
            case -1: tbRecord.Text += "\n error comparing"; break;
            case 1: tbRecord.Text += "\n P1 won."; break;
            case 2: tbRecord.Text += "\n P2 won."; break;
            case 0: {
                    tbRecord.Text += "\n WAR!";
                    for (int i = 0; i < 3; i++) {
                        DeckPOne.MoveCardFromTopToTop(WarPOne);
                        DeckPTwo.MoveCardFromTopToTop(WarPTwo);
                    }
                }; break;
        }
    }

3 个答案:

答案 0 :(得分:1)

当你这样做时

while (true) {

        }

在你的主线程上,由于CLR优先于主/ UI线程而不是计时器或后台线程,因此你的计时器会被卡住的可能性很大。

所有信号如计时器滴答等都将在MessageQueue上,并且在主线程完成之前不会被处理。

您有两个选择

 While(true)
    {
    if (WarPOne.AwaitingRecieving == 0 && WarPTwo.AwaitingRecieving == 0)
                break;

    Application.DoEvents(); // worst thing to do, but it works, flushes the message queue
    } 

其他用于线程,称为任务的线程中的最新功能非常强大,可以让您更轻松

答案 1 :(得分:0)

如果你真的想等待一些计时器滴答,为什么不订阅计时器Elapsed事件并等到#34;几个&#34;蜱已过了? (假设你在谈论标准计时器)

然而,当卡片最终到达套牌时通知等待组件可能是更好的选择。您可以使用框架提供的AutoResetEvent之类的内容,或者在新卡到达时在CardDeck类中触发CardReceived事件,等待组件可以订阅。

答案 2 :(得分:0)

你已经接受了另一个答案,但DoEvents现在真的不知道如何处理这个问题。使用&#34;任务&#34;将工作移动到托管后台线程并保持UI响应非常容易:

private void buCompW1W2_Click(object sender, EventArgs e)
{
            Task t1 = Task.Run(() =>
            {
                //starts moving card to new position
                DeckPOne.MoveCardFromTopToTop(WarPOne);
                DeckPTwo.MoveCardFromTopToTop(WarPTwo);
                //code I hope to enter to delay next steps
                Stopwatch stopwatch = Stopwatch.StartNew();
                while (true)
                { //AwaitingReceiving indicates is Deck expects to receive card, 0 means, card is already there
                  if (WarPOne.AwaitingRecieving == 0 && WarPTwo.AwaitingRecieving == 0)
                    break;
                }
                //this test must be done after cards arrive to new place, else its error (-1)
                //test compares cards in WarPOne and WarPTwo, but cards are not there yet (cards are waiting for timer tick to change position etc.) so it returns
                //en error, mechanicaly done it works like intended
                switch (CompareCards(WarPOne.TopCard, WarPTwo.TopCard))
                {
                    case -1: tbRecord.Text += "\n error comparing"; break;
                    case 1: tbRecord.Text += "\n P1 won."; break;
                    case 2: tbRecord.Text += "\n P2 won."; break;
                    case 0:
                        {
                            tbRecord.Text += "\n WAR!";
                            for (int i = 0; i < 3; i++)
                            {
                                DeckPOne.MoveCardFromTopToTop(WarPOne);
                                DeckPTwo.MoveCardFromTopToTop(WarPTwo);
                            }
                        }; break;
                }
            });
}

这实际上会启动工作,然后将控制权返回给用户。因此,当它运行时,用户可以再次单击该按钮。如果这不是您想要的,您应该禁用该按钮,直到任务完成。这可以通过添加

来完成
buCompW1W2.IsEnabled = false;

方法的开头

Dispatcher.Invoke(() => buCompW1W2.IsEnabled = true);

任务结束时。您需要在第二次调用时使用调度程序,因为只能从UI线程访问UI元素。