如何获取Task中任务的执行结果?附C#代码示例咨询
问题分析与解决方案
嘿,我来帮你捋捋这个问题——你遇到的不是作用域问题,核心是线程异步执行的顺序问题加上线程间变量的可见性问题,咱们一步步说:
为什么会拿到"first"而不是"edit"?
线程启动的异步性:当你调用
t.Start()后,Task线程是后台异步启动的,主线程根本不会等它跑任何代码,直接就执行到Console.WriteLine(p.getVar())了。这时候Task的process方法可能还没来得及执行到this.test = "edit"这一行,自然读到的是初始值。线程缓存导致的可见性问题:就算Task线程已经执行了赋值操作,由于
test变量没有任何同步机制,主线程可能依然看不到这个修改——每个线程都可能会缓存变量的本地副本,不会每次都去读取内存里的最新值。
怎么解决?
针对你的监控场景(无限循环任务),我给你两个关键修复点,再附上修改后的代码:
1. 保证变量的线程可见性
给test变量加上volatile关键字,强制每个线程读取变量时直接从内存取最新值,而不是用本地缓存:
public volatile string test = "first";
2. 让主线程等待第一次赋值完成
因为你的Task是无限循环,我们可以用一个信号量(比如ManualResetEventSlim)来通知主线程:"我已经完成第一次变量修改啦",避免主线程过早读取。
修改后的完整代码
namespace my { public class Program { public static void Main(string[] args) { Logic p = new Logic(); Task t = new Task(p.process); t.Start(); // 等待Task完成第一次变量修改 p.WaitForFirstEdit(); Console.WriteLine(p.getVar()); // 现在会输出"edit" // 如果要持续监控,可以加个循环读取 while (true) { Console.WriteLine(p.getVar()); Thread.Sleep(1000); } } } public class Logic { public volatile string test = "first"; // 用于同步的信号量 private readonly ManualResetEventSlim _firstEditDone = new ManualResetEventSlim(false); public void process() { while (true) { this.test = "edit"; // 第一次修改后发出信号,之后不用再发了 _firstEditDone.Set(); // 监控任务可以加个延迟,避免占用过多CPU Thread.Sleep(1000); } } public string getVar() { return this.test; } // 让主线程等待第一次修改完成的方法 public void WaitForFirstEdit() { _firstEditDone.Wait(); } } }
额外说明
如果你需要后续持续监控变量的变化,volatile已经能保证每次读取都是最新值;如果涉及到更复杂的读写操作(比如多个线程同时修改),那最好用lock或者线程安全的容器(比如ConcurrentDictionary这类)来保证线程安全。
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

