【问题标题】:Sleep method doesn't work properly睡眠方法无法正常工作
【发布时间】:2014-04-08 21:15:38
【问题描述】:

好的,我有一个棋盘应用程序。该应用程序在一个组框中有 64 个面板。这些面板用表达式 CHessBoardPanels{x,y) 标识。我正在使用它来更改面板的背景颜色。我希望在 chessPanel.BackGround 变为红色和面板变回白色之间有一点延迟。(大约 1 到 2 秒的延迟) 我已经尝试过睡眠功能,但它基本上会锁定应用程序,直到任务完成

这是我尝试过的代码:

for (int Row = 7; Row > 3; --Row)
{
    chessBoardPanels[ Column ,Row].BackColor = Color.Red;
    ++Column;
    //Add text to Moves TextBox
    MovesText.AppendFormat("WhtB {0} {1}{2}", ColumnText, RowText, Environment.NewLine);
    MovesTxt.Text = MovesText.ToString();
    ++ColumnText;
    --RowText;
}

//Start White Horizonal Drill
Column = 0;
Thread.Sleep(5000);             //This does not delay proerperly
for (int Row = 7; Row > 4; --Row)
{
    chessBoardPanels[Column, Row].BackColor = Color.White;
    ++Column;
    //Add text to Moves TextBox
    MovesText.AppendFormat("WhtB {0} {1}{2}", ColumnText, RowText, Environment.NewLine);
    MovesTxt.Text = MovesText.ToString();
    ++ColumnText;
    --RowText;
} 

我正在使用 .Net framework 4.0,因为 Visual Studio 2010 不支持 4.5

【问题讨论】:

  • 请修正您的代码格式和缩进。现在它几乎无法阅读。
  • “正确”是什么意思? Sleep 方法应该在应用程序运行时锁定您的应用程序,所以如果它这样做,它会“正常”工作...
  • 你已经让线程休眠了,你的问题是:它为什么休眠?
  • 我不确定你所说的格式不可读是什么意思....
  • 我真正想要的第一个循环是改变 ChessBoardPanels 的背景......然后等待几秒钟......然后将它们改回白色。从昨天早上开始我就一直坚持这个

标签: c# winforms


【解决方案1】:

这就是 Sleep 的作用,它暂停线程。

您需要使用Timer 控件,并创建一个颜色变化的队列,并让计时器控件定期调用事件处理程序,如下所示:

(在您的 Form 类中):

Timer timer = new Timer();

(在表单的构造函数中):

timer.Tick += new EventHandler(timer_Tick);
timer.Interval = 500; // every 1/2 second
timer.Enabled = true;
timer.Start();

然后你的事件处理程序会做这样的事情:

void timer_Tick(object sender, EventArgs e)
{
    // Read a queue, that contains timings
    var nextItem = PeekAtQueue();
    if ((nextItem != null) && (nextItem.WhenToChangeColor <= DateTime.Now))
    {
        var item = TakeFromQueue(); // as opposed to just peeking
        ChangeColor(item);
    }
} 

这是做什么的? (当然这段代码不是 100% 完整的,你必须自己添加队列访问方法,这取决于你想要/可以使用什么)

  • 看到 Sleep() 会暂时冻结您的应用程序,您需要一个 允许您仍然与表单交互的解决方案,同时 仍然有延迟并在延迟之后做某事。
  • 所以你 需要使用计时器在以后执行某些操作。计时器 在此示例中每 1/2 秒执行一次,但您可以使用任何 您选择的时间间隔。
  • 重点是,因为这个计时器和这个 配置,某个方法——事件处理程序——被执行 每 1/2 秒,或您选择的间隔。
  • 那么你能做什么 然后要做的是,当您希望稍后发生某种颜色变化时, 排队一个描述颜色变化的对象,例如{E5, "red", today at 04:20:30 PM}
  • 由执行的事件处理程序 计时器每次都会偷看队列中是否有东西,并且 看看它是什么。它检查是否“改变的时刻 颜色”,如队列对象中所述,现在或已经 通过了。如果是这样,它会改变颜色。如果没有,它会将项目留在 队列的顶部,以及下一次事件处理程序获取 再次执行(1/2 秒后),它将执行相同的检查 再次。
  • 一旦完成颜色更改,对象就会从 排队。

【讨论】:

  • 值得一提的是还有其他类型的计时器,但这是使用System.Windows.Forms.Timer
  • 如果你在Form中使用上面的代码,你会得到这样的结果,是的。
  • 好的,但是 PeekAtQueue 方法不存在
  • @RoyDictus:我认为解释框架中还有其他名为“Timer”的类有其他用途可能是有教育意义的。我想我可以从这里链接到stackoverflow.com/questions/21547980/which-c-sharp-timer。 :)
  • @user3501478:你必须自己写,是的,我不会做你所有的工作:)答案让你知道如何解决你的问题,同时留下具体的东西到你的应用程序给你。请注意,答案也没有告诉您使用哪个队列类或如何初始化它...
【解决方案2】:

考虑改用Timer 类。这应该允许您在不锁定线程的情况下延迟您的应用程序。

【讨论】:

    【解决方案3】:

    我已经尝试过睡眠功能,但它基本上会锁定应用程序 直到任务完成

    您需要将应用程序的逻辑移至主(或 UI)线程。如果您在主 (UI) 线程中调用 Thread.Sleep,您的应用程序将“冻结”,因为 Windows 事件处理循环被阻塞。

    你可以使用的东西:

    • 用于执行游戏逻辑的新线程、任务、后台工作者
    • 定时器
    • 从另一个线程更新 GUI

    【讨论】:

      【解决方案4】:

      Sleep 将锁定当前线程,这意味着如果它是主 UI 线程,则不会处理任何用户输入 - 理想情况下,您应该在该点设置一个沙漏光标。

      要做你想做的事,我认为你需要启动一个后台计时器,然后在回调上设置颜色,然后取消计时器。

      当计时器计时结束时,主 UI 仍会响应。 您可能还会发现超过 1 秒的延迟对用户来说感觉延迟太长,但计时器周期以毫秒为单位,因此您可以定义更短的延迟。

      【讨论】:

        【解决方案5】:

        尝试以下操作:

        Task.Run(() => Thread.Sleep(5000)).Wait();
        

        【讨论】:

        • 但是Run方法不存在
        猜你喜欢
        • 2017-10-27
        • 1970-01-01
        • 1970-01-01
        • 2021-01-15
        • 1970-01-01
        • 1970-01-01
        • 2016-09-27
        • 1970-01-01
        • 2019-06-02
        相关资源
        最近更新 更多