Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 线程的替代品。在windows窗体中睡眠,不使用计时器_C#_Multithreading_Winforms_Timer - Fatal编程技术网

C# 线程的替代品。在windows窗体中睡眠,不使用计时器

C# 线程的替代品。在windows窗体中睡眠,不使用计时器,c#,multithreading,winforms,timer,C#,Multithreading,Winforms,Timer,我正在使用线程。在windows窗体C#中睡眠。使用它会导致表单不响应。 使用定时器也不符合我的目的 示例代码: if(......) // There are many if with difrent components and many Thread.sleep { button.visible=true; Thread.sleep(1000); GotoMeasurementMode(3000); Thread.sleep(3000)

我正在使用线程。在windows窗体C#中睡眠。使用它会导致表单不响应。 使用定时器也不符合我的目的

示例代码:

if(......)    // There are many if with difrent components and many Thread.sleep
{
      button.visible=true;
      Thread.sleep(1000);
      GotoMeasurementMode(3000);
      Thread.sleep(3000);
      query(device.Text);
      Thread.sleep(7000);
      StopMeasurement();
      Thread.sleep(4000);
 }
使用上述代码会导致形式上的不负责任。使用计时器将导致嵌套计时器。这对我来说是不必要的。
请告诉我windows窗体中的其他选项。需要命令之间的特定暂停。

最简单的选择是使用此模型:

public async void button1_Click(object sender, EventArgs args)
{
    if(condition)
    {
        button.visible=true;
        await Task.Delay(1000);
        GotoMeasurementMode(3000);
        await Task.Delay(3000);
        query(device.Text);
        await Task.Delay(7000);
        StopMeasurement();
        await Task.Delay(4000);
    }
}
如果你没有访问C#5.0的权限,你可以在4.0中完成。您需要从自己的
Delay
方法开始,因为.NET 4.0中不存在这种方法:

public static Task Delay(int milliseconds)
{
    var tcs = new TaskCompletionSource<bool>();
    var timer = new System.Threading.Timer(o => tcs.SetResult(false));
    timer.Change(milliseconds, -1);
    return tcs.Task;
}
这与第一个代码段将被编译成的代码非常相似,但显然第一个代码段要漂亮得多,所以如果可能的话,您应该使用它

如果我们回到C#3.0,那么我们将无法访问
任务
,这意味着我们将重新使用计时器和回调。我们将从这个简单的助手方法开始,为我们管理任务:

public static void ExecuteIn(int milliseconds, Action action)
{
    var timer = new System.Windows.Forms.Timer();
    timer.Tick += (s, e) => { action(); timer.Stop(); };
    timer.Interval = milliseconds;
    timer.Start();
}
然后我们就可以嵌套调用到这个:

ExecuteIn(1000, () =>
{
    GotoMeasurementMode(3000);
    ExecuteIn(3000, () =>
    {
        query(device.Text);
        ExecuteIn(7000, () => StopMeasurement());
    });
});

虽然可以在C#3.0中重新创建一个
任务
(它不利用任何4.0语言功能),而且现有的库也可以这样做,但这将更加复杂。

将上述代码放在后台线程中,这样就不会阻塞UI线程。假设你的方法在等待之间需要UI访问,他们可以使用控制。开始调用在UI线程上进行更新。

你应该考虑一个. 目前只有.NET framework 4.5支持异步等待机制

如果您正在寻找向后兼容的解决方案,您应该在上查看此链接

后台工作程序将在一个单独的线程上下文中异步执行您的任务,以便长时间运行进程,保持您的UI响应能力


希望它对多线程有帮助,winforms程序的UI线程上没有任何其他选项调用Thread.Sleep()。用户界面进入睡眠状态。改用定时器。我个人认为永远不要调用
Thread.Sleep()
,句号。它的存在不可避免地带来了比它解决的问题更多的问题。但这是另一个时间的问题。@cHao我认为在某些情况下调用
线程是有效的。Sleep(0)
。@cHao-请建议在从多个线程调用、从多个位置调用和调用堆栈中的几个级别调用的函数中延迟五秒钟。这将是理想的选择,但只在.NET4.5上可用。好吧,如果那样做的话,我会再次爱上C#的。@JohnField在那里还添加了一个C#4.0解决方案。如果这很重要的话,也可以很容易地修改它,使其在3.0或2.0中工作,但这需要更多的工作。C#4.0有一个更简单的解决方案:添加NuGet包
Microsoft.Bcl.Async
,然后使用
TaskEx.Delay
而不是
Task.Delay
@StephenCleary,对我来说,编写/复制一个四行方法比引用一个附加程序集更容易。不过,这可能是一个更好的主意,特别是如果您经常使用它,因为该实现可以处理一些边缘情况,但实际上并没有。如果你正在利用库中的其他功能,那么这可能会更容易。你的意思是说,将包含所有If语句的整个代码放在一个线程中?但这会在一段较长的时间内阻塞一个线程,与异步执行代码相比,这是不必要的浪费资源。是-在单独的线程中运行所有内容(使用您选择的任务、BackgroundWorker或线程启动)。休眠和非基于UI的代码将异步工作。任何访问UI组件的操作都会引发异常,所以请将该部分包装在BeginInvoke中。请参阅Servy-休眠线程阻塞该线程,但它不会旋转CPU,这类似于使用SpinWait,我不提倡使用它。@Servy-是的。这将是数千个,因此与许多应用程序无关。你不需要使用.NET4.5来使用异步编程,它只是让它更容易。
ExecuteIn(1000, () =>
{
    GotoMeasurementMode(3000);
    ExecuteIn(3000, () =>
    {
        query(device.Text);
        ExecuteIn(7000, () => StopMeasurement());
    });
});