簡體   English   中英

簡單等待,直到后台進程結束C#

[英]Simple wait till background process ends C#

我有這個(可能是個小問題)。 我正在移動卡片的形式,在一個過程中,我需要等待,直到卡片完成移動為止(並添加到CardDeck類中)。 由於班級設計的原因,我無法將卡添加到新的Deck中。 我需要做的就是等待代碼繼續運行幾個計時器(在后台運行)。 我在這里在Stackoverflow上找到了等待例程,但是在這種情況下它不能工作,而Im在使用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;
        }
    }

當你這樣做

while (true) {

        }

在主線程上,計時器很可能會被卡住,因為CLR優先使用Main / UI線程,而不是使用計時器或后台線程。

所有信號(如計時器滴答聲等)都將在MessageQueue上,並且直到您的Main線程完成后才會進行處理。

你有兩個選擇

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

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

否則進行線程處理,線程中稱為任務的最新功能很強大,可以使您更輕松

如果你真的想只是等待一些計時器滴答,你為什么不訂閱計時器Elapsed事件,等到“幾”滴答已經過去了? (假設您正在談論標准計時器)

但是,當卡最終到達甲板時通知等待組件可能是一個更好的選擇。 您可以使用框架提供的AutoResetEvent之類的東西,也可以在新卡到達時在CardDeck類中觸發CardReceived事件,等待組件可以預訂。

您已經接受了另一個答案,但是DoEvents確實不是如今的處理方式。 使用“任務”,將工作移至托管后台線程並使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線程訪問。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM