[英]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.