控制台应用使用Thread.Sleep无等待效果?输出时间均相同
控制台命令执行等待逻辑异常问题解决
问题说明
开发的控制台应用未按预期实现等待逻辑,所有命令输出时间几乎一致。需求如下:
- 命令按顺序执行,必须等待上一个命令的
WaitAfterExecution完成后再执行下一个命令 - 允许长时间数据获取类任务并行执行
使用Thread.Sleep未达到预期效果,尝试单独线程执行也无效,相关代码、示例及输出如下:
原代码实现
命令定义与扩展方法
public class Qsend: IQCommand { public Qsend(Action p, int v1, int v2, string v3) { OnCommand = p; WaitBeforeExecution = v1; WaitAfterExecution = v2; Name = v3; } public Action OnCommand { get ; set ; } public int WaitBeforeExecution { get ; set ; } public int WaitAfterExecution { get ; set ; } public string Name { get ; set ; } } public interface IQCommand { Action OnCommand { get; set; } int WaitBeforeExecution { get; set; } int WaitAfterExecution { get; set; } string Name { get; set; } } public static class CExtensions { public static void ProcessThis(this IQCommand irc) { Console.WriteLine("Process This Started!!!"); if (irc == null) return; if (irc.OnCommand == null) return; if (irc.WaitBeforeExecution > 0) System.Threading.Thread.Sleep(irc.WaitBeforeExecution); irc.OnCommand.Invoke(); if (irc.WaitAfterExecution > 0) System.Threading.Thread.Sleep(irc.WaitAfterExecution); Console.WriteLine("Process This End!!!"); } }
使用示例
using System.Diagnostics; List<IQCommand> commands = new List<IQCommand>(); commands.Add(new Qsend(() => { Console.WriteLine($"Command 1 {DateTime.Now.ToString(\"HH:mm:ss.ffffff\")}"); }, 3, 6, "Name 1")); commands.Add(new Qsend(() => { Console.WriteLine($"Command 2 { DateTime.Now.ToString(\"HH:mm:ss.ffffff\")}"); }, 5, 10, "Name 2")); Console.WriteLine($"Before EXE {DateTime.Now.ToString(\"HH:mm:ss.ffffff\")}"); foreach (var item in commands) { Console.WriteLine(item.Name); item.ProcessThis(); } Console.WriteLine($"AFTER EXE {DateTime.Now.ToString(\"HH:mm:ss.ffffff\")}");
实际输出
Before EXE 15:11:13.482163 Name 1 Process This Started!!! Command 1 15:11:13.533112 Process This End!!! Name 2 Process This Started!!! Command 2 15:11:13.563431 Process This End!!! AFTER EXE 15:11:13.578287
尝试过的线程方案
Thread thr = new Thread(new ThreadStart(() => { Console.WriteLine($"Before EXE {DateTime.Now.ToString(\"HH:mm:ss.ffffff\")}"); foreach (var item in commands) { Console.WriteLine(item.Name); item.ProcessThis(); } Console.WriteLine($"AFTER EXE {DateTime.Now.ToString(\"HH:mm:ss.ffffff\")}"); })); thr.Start();
问题根源与解决方案
问题根源
- 等待参数值过小:示例中传入的
WaitBeforeExecution和WaitAfterExecution为3、6、5、10,这些是毫秒级数值,时间间隔极短,导致视觉上几乎同时执行。 - 阻塞式等待:
Thread.Sleep会阻塞当前线程,无法实现非阻塞的等待,也不利于并行执行长时间任务。 - 不支持异步逻辑:原代码使用
Action,无法直接处理异步任务,限制了并行场景的实现。
修改后的实现
1. 调整命令接口与类,支持异步
public interface IQCommand { Func<Task> OnCommand { get; set; } int WaitBeforeExecution { get; set; } int WaitAfterExecution { get; set; } string Name { get; set; } } public class Qsend : IQCommand { public Qsend(Func<Task> p, int v1, int v2, string v3) { OnCommand = p; WaitBeforeExecution = v1; WaitAfterExecution = v2; Name = v3; } public Func<Task> OnCommand { get; set; } public int WaitBeforeExecution { get; set; } public int WaitAfterExecution { get; set; } public string Name { get; set; } }
2. 异步扩展方法,非阻塞等待
public static class CExtensions { public static async Task ProcessThisAsync(this IQCommand irc) { Console.WriteLine("Process This Started!!!"); if (irc == null || irc.OnCommand == null) return; if (irc.WaitBeforeExecution > 0) await Task.Delay(irc.WaitBeforeExecution); // 异步执行命令逻辑,支持并行任务 await irc.OnCommand.Invoke(); if (irc.WaitAfterExecution > 0) await Task.Delay(irc.WaitAfterExecution); Console.WriteLine("Process This End!!!"); } }
3. 最终使用示例(顺序执行+并行任务)
using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; class Program { static async Task Main(string[] args) { List<IQCommand> commands = new List<IQCommand>(); // 命令1:包含并行数据获取任务 commands.Add(new Qsend(async () => { Console.WriteLine($"Command 1 {DateTime.Now.ToString("HH:mm:ss.ffffff")}"); // 模拟长时间并行数据获取,后台线程执行 var dataFetchTask = Task.Run(() => { Thread.Sleep(5000); // 模拟5秒数据获取 Console.WriteLine($"Command 1 数据获取完成 {DateTime.Now.ToString("HH:mm:ss.ffffff")}"); }); // 此处可继续执行同步逻辑,无需等待数据任务完成 // await dataFetchTask; // 若需等待数据获取完成再继续,取消注释 }, 3000, 6000, "Name 1")); // 命令2:普通同步命令 commands.Add(new Qsend(() => { Console.WriteLine($"Command 2 {DateTime.Now.ToString("HH:mm:ss.ffffff")}"); }, 5000, 10000, "Name 2")); Console.WriteLine($"Before EXE {DateTime.Now.ToString("HH:mm:ss.ffffff")}"); // 顺序执行每个命令,等待上一个完成再执行下一个 foreach (var item in commands) { Console.WriteLine(item.Name); await item.ProcessThisAsync(); } Console.WriteLine($"AFTER EXE {DateTime.Now.ToString("HH:mm:ss.ffffff")}"); } }
修改说明
- 将
Action改为Func<Task>,支持异步命令逻辑,便于处理并行任务 - 用
Task.Delay替代Thread.Sleep,实现非阻塞等待,避免占用线程资源 - 长时间数据获取任务通过
Task.Run放到后台线程执行,实现并行处理 - 主方法改为
async Task Main,支持异步等待,确保命令按顺序执行
内容的提问来源于stack exchange,提问作者Dev
相关产品推荐
相关产品推荐

