我有这个(可能是微不足道的问题)。我在表格上移动卡片,在一个过程中我需要等待,直到卡片完成移动(并添加到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;
}
}
答案 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元素。