首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >在不锁定GUI的情况下暂停执行方法。C#

在不锁定GUI的情况下暂停执行方法。C#
EN

Stack Overflow用户
提问于 2009-09-13 17:45:12
回答 4查看 19.9K关注 0票数 5

我正在为我的OOP入门论文中的一个项目在C#上做一个纸牌游戏,现在游戏已经开始工作了,但我正在为图形用户界面添加"flair“。

目前,牌是发牌的,并立即出现在UI上。我想在发完一张牌后,在发下一张牌之前先暂停一下。

当游戏开始时,运行以下代码来填充表示它们的PictureBoxes (最终将是一个循环):

代码语言:javascript
运行
AI代码解释
复制
        cardImage1.Image = playDeck.deal().show();
        cardImage2.Image = playDeck.deal().show();
        cardImage3.Image = playDeck.deal().show();
        cardImage4.Image = playDeck.deal().show();
        cardImage5.Image = playDeck.deal().show();
        ...

我尝试使用System.Threading.Thread.Sleep(100);在每个deal()之间和每个方法中使用.show(),但它所实现的只是锁定我的图形用户界面,直到所有休眠处理完毕,然后一次显示所有卡片。

我也尝试过使用计时器和while循环的组合,但效果相同。

达到预期结果的最佳方式是什么?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-09-13 17:53:06

问题是,您在UI上运行的任何代码都会阻塞UI并冻结程序。当您的代码正在运行时(即使它正在运行Thread.Sleep),发送到UI的消息(例如绘制或单击)将不会被处理(直到您退出事件处理程序时控件返回到消息循环),从而导致它冻结。

最好的方法是在后台线程上运行,然后在休眠之间Invoke到UI线程,如下所示:

代码语言:javascript
运行
AI代码解释
复制
//From the UI thread,
ThreadPool.QueueUserWorkItem(delegate {
    //This code runs on a backround thread.
    //It will not block the UI.
    //However, you can't manipulate the UI from here.
    //Instead, call Invoke.
    Invoke(new Action(delegate { cardImage1.Image = playDeck.deal().show(); }));
    Thread.Sleep(100);

    Invoke(new Action(delegate { cardImage2.Image = playDeck.deal().show(); }));
    Thread.Sleep(100);

    Invoke(new Action(delegate { cardImage3.Image = playDeck.deal().show(); }));
    Thread.Sleep(100);

    //etc...
});
//The UI thread will continue while the delegate runs in the background.

或者,您可以制作一个计时器,并在下一个计时器滴答中显示每个图像。如果你使用计时器,你一开始要做的就是启动计时器;不要等待它,否则你会引入同样的问题。

票数 17
EN

Stack Overflow用户

发布于 2009-09-13 17:53:52

最便宜的解决方法是调用Application.DoEvents()进行循环,但更好的替代方法是设置一个System.Windows.Forms.Timer,您可以在它第一次运行后停止它。在这两种情况下,您都需要一些指示器来告诉您的UI事件处理程序忽略输入。如果足够简单,您甚至可以仅使用timer.Enabled属性来实现此目的。

票数 3
EN

Stack Overflow用户

发布于 2009-09-13 18:45:36

通常,我会简单地推荐这样的函数来执行暂停,同时允许UI是交互式的。

代码语言:javascript
运行
AI代码解释
复制
  private void InteractivePause(TimeSpan length)
  {
     DateTime start = DateTime.Now;
     TimeSpan restTime = new TimeSpan(200000); // 20 milliseconds
     while(true)
     {
        System.Windows.Forms.Application.DoEvents();
        TimeSpan remainingTime = start.Add(length).Subtract(DateTime.Now);
        if (remainingTime > restTime)
        {
           System.Diagnostics.Debug.WriteLine(string.Format("1: {0}", remainingTime));
           // Wait an insignificant amount of time so that the
           // CPU usage doesn't hit the roof while we wait.
           System.Threading.Thread.Sleep(restTime);
        }
        else
        {
           System.Diagnostics.Debug.WriteLine(string.Format("2: {0}", remainingTime));
           if (remainingTime.Ticks > 0)
              System.Threading.Thread.Sleep(remainingTime);
           break;
        }
     }
  }

但是,当从事件处理程序(如单击按钮)中调用此类解决方案时,使用这种解决方案似乎有些复杂。我认为系统希望按钮单击事件处理程序在继续处理其他事件之前返回,因为如果我在事件处理程序仍在运行时再次尝试单击,即使我试图拖动窗体而不是单击按钮,按钮也会再次按下。

所以这是我的另一个选择。在窗体中添加一个计时器,并创建一个牌手类,通过与该计时器进行交互来处理卡片。设置计时器的Interval属性,使其与您希望发牌的间隔相匹配。下面是我的示例代码。

代码语言:javascript
运行
AI代码解释
复制
public partial class Form1 : Form
{

  CardDealer dealer;

  public Form1()
  {
     InitializeComponent();
     dealer = new CardDealer(timer1);
  }

  private void button1_Click(object sender, EventArgs e)
  {
     dealer.QueueCard(img1, cardImage1);
     dealer.QueueCard(img2, cardImage2);
     dealer.QueueCard(img3, cardImage1);
  }
}

class CardDealer
{
  // A queue of pairs in which the first value represents
  // the slot where the card will go, and the second is
  // a reference to the image that will appear there.
  Queue<KeyValuePair<Label, Image>> cardsToDeal;
  System.Windows.Forms.Timer dealTimer;

  public CardDealer(System.Windows.Forms.Timer dealTimer)
  {
     cardsToDeal = new Queue<KeyValuePair<Label, Image>>();
     dealTimer.Tick += new EventHandler(dealTimer_Tick);
     this.dealTimer = dealTimer;
  }

  void dealTimer_Tick(object sender, EventArgs e)
  {
     KeyValuePair<Label, Image> cardInfo = cardInfo = cardsToDeal.Dequeue();
     cardInfo.Key.Image = cardInfo.Value;
     if (cardsToDeal.Count <= 0)
        dealTimer.Enabled = false;
  }

  public void QueueCard(Label slot, Image card)
  {
     cardsToDeal.Enqueue(new KeyValuePair<Label, Image>(slot, card));
     dealTimer.Enabled = true;
  }
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1419363

复制
相关文章
关于js暂停执行的方法
JavaScript是一门单线程但是可处理异步任务的脚本语言,是没有提供sleep等类似的方法的,当有需求需要暂停js脚本时,可以使用以下的方法  单线程分析:http://blog.csdn.net/talking12391239/article/details/21168489
仙士可
2019/12/19
7.2K0
关于js暂停执行的方法
【DB笔试面试599】在Oracle中,如何在不执行SQL的情况下获取执行计划?
♣ 题目部分 在Oracle中,如何在不执行SQL的情况下获取执行计划? ♣ 答案部分 1、“EXPLAIN PLAN FOR SQL”不实际执行SQL语句,生成的计划未必是真实执行的计划。但是,必
AiDBA宝典
2019/09/29
2.5K0
dotnet 使用 FormatterServices 的 GetUninitializedObject 方法在丢失 DLL 情况下能否执行
在 dotnet 里面,可以使用 FormatterServices 的 GetUninitializedObject 方法可以实现只创建对象,而不调用对象的构造函数方法。而如果在使用此方法时,存在了 DLL 缺失的情况,此时能否让此方法运行通过,创建出空的对象
林德熙
2021/12/23
6220
dotnet 使用 FormatterServices 的 GetUninitializedObject 方法在丢失 DLL 情况下能否执行
Spring Batch 在默认情况下的任务执行
考察项目:https://github.com/cwiki-us-spring/cwiki-us-spring-batch-examples 你可以 Check out 到本地后运行:
HoneyMoose
2020/02/19
6670
C# 定时执行方法
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/160676.html原文链接:https://javaforall.cn
全栈程序员站长
2022/09/09
1.3K0
Spring Batch 在默认情况下的任务执行
考察项目:https://github.com/cwiki-us-spring/cwiki-us-spring-batch-examples 你可以 Check out 到本地后运行:
HoneyMoose
2020/02/24
1.2K0
C# Monitor:锁定资源
C#中, 通过System.Threading.Monitor类可以实现多线程中对某些代码块的同步访问,以确保数据的安全性。
zls365
2020/08/19
9040
C# Monitor:锁定资源
C# Task 暂停与取消
②task的线程管控方法Task..Wait(time),Task.WaitAll(), Task.WaitAny(),task.ContinueWith.
用户9127601
2021/11/01
2K0
C#在.NET编译执行过程
1..NET语言的编译器接受源代码文件,并生成名为程序集的输出文件。 程序集要么是可执行的,要么是DLL 程序集里的代码并不是本机代码,而是一种名称为CIL的中间语言 程序集包含如下信息: 程序的CIL 程序中使用的类型的元数据 对其他程序集引用的元数据 2.   程序的编译过程    程序的CIL直到它被调用运行时才会被编译成本机代码。在运行时,CLR执行下面步骤: 检查程序集的安全特性 在内存中分配空间 把程序集中的可执行代码发送给实时编译器(JIT),把其中的一部分编译成本机代码。 程序集中的可执行
hbbliyong
2018/03/06
1.3K0
C#在.NET编译执行过程
C#在.NET编译执行过程
程序的CIL直到它被调用运行时才会被编译成本机代码。在运行时,CLR执行下面步骤:
用户8983410
2021/09/26
7260
C#执行Javascript代码的几种方法
一、开源项目 Javascript .NET 地址: http://javascriptdotnet.codeplex.com/ 它是Google Chrome V8引擎在.NET上的封装,功能完善,性能相对较高,推荐使用! (缺点就是asp.net web应用上,好象会报错) 示例代码: using Noesis.Javascript; using System; using System.Collections.Generic; namespace JsCSharp { class Progr
菩提树下的杨过
2018/01/24
5.5K0
【JavaSE专栏81】线程休眠,一种暂停线程执行的方法
本文讲解了 Java 中线程休眠的语法和应用场景,并给出了样例代码。线程休眠是一种暂停线程执行的方法。当线程调用 Thread.sleep() 方法时,它会进入指定的时间段的休眠状态,暂停当前线程的执行,让出 CPU 资源给其他线程。
Designer 小郑
2023/08/20
5240
【JavaSE专栏81】线程休眠,一种暂停线程执行的方法
为什么TableView 的代理方法cellForRowAtIndexPath 不执行问题
检查一下 这个方法如果返回值为 0 或 nil 就不会执行 cellForRowAtIndexPath 方法 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 0; 或 return nil; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIn
LeeCen
2018/10/11
1.4K0
Kali-命令-锁定当前版本,不更锁定软件包
当我们更新所有软件包时,可能不想更新某一个软件时,可以保留这个版本不更新 [软件包名称]:可以使用 查看当前系统中所有软件包状态 命令查看软件包名称
用户9006224
2022/12/21
4270
Kali-命令-锁定当前版本,不更锁定软件包
使用JPA原生SQL查询在不绑定实体的情况下检索数据
在这篇博客文章中,我将与大家分享我在学习过程中编写的JPA原生SQL查询代码。这段代码演示了如何使用JPA进行数据库查询,而无需将数据绑定到实体对象。通过本文,你将了解如何使用原生SQL查询从数据库中高效地检索数据。
高久峰
2023/08/07
8070
在公司制度不规范的情况下,如何做好测试工作?
遇到这个好机会你还在等什么?如果说这个公司已经足够好了,那他还请你过来做什么?你的能力还足以让公司有更高的提升么?
软件测试君
2019/11/04
1.2K0
C#如何控制方法的执行时间,超时则强制退出方法执行
http://www.blue1000.com/bkhtml/c17/2013-01/71047.htm
跟着阿笨一起玩NET
2018/09/19
4.2K0
C# dotnet 使用 TaskCompletionSource 实现暂停功能
在 C# 里面,可以使用 dotnet 的 TaskCompletionSource 方法自己实现一个异步任务,这个任务可以方便设置任务是否完成等做到让等待的过程继续或等待。根据这个功能可以解决在复杂的功能里面通过异步等待的方法实现暂停。做法就是等待一个异步任务,如果这个功能处于暂停,那么只需要让这个异步任务不结束,此时整个功能就会在等待,直到设置了异步任务完成
林德熙
2020/05/12
2.1K0
点击加载更多

相似问题

Java GUI,需要在不冻结GUI的情况下暂停方法

50

在Java GUI中暂停执行

41

在暂停活动的情况下执行方法?

36

睡眠方法锁定我的GUI

40

如何在不暂停整个程序的情况下让方法暂停?

40
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文