【问题标题】:C#: How to execute thread without halting program executionC#:如何在不停止程序执行的情况下执行线程
【发布时间】:2015-03-02 17:33:07
【问题描述】:

我正在制作一个记忆游戏。每当用户单击按钮时,就会显示图像。然后用户必须单击另一个按钮。如果两个图像匹配,则按钮将替换为刻度线。如果没有,则用户有 1 秒的间隙来记住图像位置。然后,图像被隐藏并显示按钮。 我做了 1 秒的间隔 线程.Sleep(1000)

我在游戏中嵌入了一个倒计时计时器,其持续时间为 30 秒。我已经放置了一个标签,显示每个时钟滴答的 30 秒倒计时。


现在实际的问题是,每当调用 Thread.Sleep(1000) 时,计时器就会停止。 1 秒后,它恢复。无论线程如何,我都希望这个计时器执行。请帮忙。

【问题讨论】:

  • 解决方案是不阻塞 UI 线程,而不是阻塞 UI 线程并让 UI 仍然响应。
  • 如果你有一个计时器,你为什么要首先调用 Thread.Sleep(1000) ?请发布一些代码供我们研究。
  • 因为计时器与您执行它的线程位于同一线程上,这也是 Thread.Sleep 所在的线程 - 这就是问题所在。你需要分开 2....当你在做 Thread.Sleep 时,你阻塞了你的主线程(在这种情况下是 UI)线程。显示您当前使用的代码!
  • System.Threading.Thread.Sleep != System.Threading.Timer

标签: c# multithreading timer


【解决方案1】:

有点难以准确理解你在问什么,如果我误解了你,很抱歉,但我想你问的是如何在不阻塞 UI 线程的情况下在新线程上使用计时器更新 UI?答案是您无法在创建它的线程之外的线程中更新 UI 控件。相反,您必须创建一个委托来为您执行此操作。

所以,这给了你一个例外,因为计时器结束时的回调 UpdateText 在计时器线程上执行,而不是在主 UI 线程上:

private void button1_Click(object sender, EventArgs e)
{
    System.Threading.Timer timer = new System.Threading.Timer(UpdateText, null, 1000, System.Threading.Timeout.Infinite);
}

public void UpdateText(object state)
{
    this.textBox1.AppendText("Ouch!" + Environment.NewLine);
}

然而,这是按预期工作的:当您单击按钮时,一秒钟后会出现“哎哟!”出现在文本框中。这是因为在带有 MethodInvoker 委托的文本框控件上使用 BeginInvoke 方法会导致委托在拥有该控件的线程(即主 UI 线程)上执行,而不是在计时器线程上执行:

private void button1_Click(object sender, EventArgs e)
{
    System.Threading.Timer timer = new System.Threading.Timer(UpdateText, null, 1000, System.Threading.Timeout.Infinite);
}

public void UpdateText(object state)
{
    MethodInvoker action = delegate
    {
        this.textBox1.AppendText("Ouch!" + Environment.NewLine);
    };

    this.textBox1.BeginInvoke(action);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-29
    • 1970-01-01
    • 2016-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多