C#线程使用及高CPU占用问题:如何高效创建并终止线程
解决C#线程高CPU占用与可控终止问题
首先得先揪出你现有代码里的几个明显问题,这些问题直接导致了CPU拉满:
Thread.Sleep(1000)写在了while(true)循环外面,等于这个休眠根本不会被执行,线程会一直疯狂循环调用GetPage,CPU不跑满才怪- 方法名拼写错误:
Getpage()应该是GetPage() - 弹窗拼写错误:
MessegeBox要改成MessageBox
接下来针对你的核心需求——安全终止线程+高效发起大量请求且避免CPU占用过高,给你两个实用方案:
方案一:用CancellationToken实现优雅线程终止 + 合理控制循环频率
线程Abort()方法已经被标记为过时且不安全,推荐用CancellationToken来优雅终止线程。另外,哪怕要极致快速请求,循环里也得加个极短的等待(哪怕几毫秒),不然线程会一直空转占满CPU:
private CancellationTokenSource _cts; void myButton_Click(object sender, RoutedEventArgs e) { // 先停止之前的线程(如果存在) _cts?.Cancel(); _cts = new CancellationTokenSource(); var token = _cts.Token; new Thread(() => { while (!token.IsCancellationRequested) { GetPage("你的目标URL"); // 补上GetPage需要的URL参数 // 这里可以根据需求调整等待时长,哪怕10ms也能大幅降低CPU占用 // 如果要极致快速,也可以用Thread.Sleep(1),完全无等待的话CPU还是会拉满 Thread.Sleep(10); } Console.WriteLine("线程已正常终止"); }).Start(); } // 绑定到停止按钮的方法,用来终止线程 void StopThreadBtn_Click(object sender, RoutedEventArgs e) { _cts?.Cancel(); _cts?.Dispose(); _cts = null; } public static void GetPage(String url) { try { HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url); // 用using语句自动释放响应资源,不用手动Close using (HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse()) { if (myHttpWebResponse.StatusCode == HttpStatusCode.OK) Console.WriteLine("\r\nResponse Status Code is OK and StatusDescription is: {0}", myHttpWebResponse.StatusDescription); } } catch (WebException e) { MessageBox.Show($"\r\nWebException Raised. The following error occurred : {e.Status}"); } catch (Exception e) { MessageBox.Show($"\nThe following Exception was raised : {e.Message}"); } }
方案二:用异步IO替代线程(更适合HTTP这类IO密集型任务)
HTTP请求属于IO密集型操作,用异步await可以让线程在等待响应时被释放去处理其他任务,比创建大量线程更高效,CPU占用也更低,同时同样支持CancellationToken控制终止:
private CancellationTokenSource _cts; async void myButton_Click(object sender, RoutedEventArgs e) { _cts?.Cancel(); _cts = new CancellationTokenSource(); var token = _cts.Token; try { while (!token.IsCancellationRequested) { await GetPageAsync("你的目标URL"); // 同样加短暂等待避免CPU空转 await Task.Delay(10, token); } } catch (OperationCanceledException) { Console.WriteLine("异步任务已终止"); } } void StopThreadBtn_Click(object sender, RoutedEventArgs e) { _cts?.Cancel(); _cts?.Dispose(); _cts = null; } public static async Task GetPageAsync(String url) { try { // HttpClient推荐复用,这里为了简洁直接在方法内创建,实际项目可以全局复用实例 using (var httpClient = new HttpClient()) { var response = await httpClient.GetAsync(url); if (response.IsSuccessStatusCode) Console.WriteLine("\r\nResponse Status Code is OK and Reason Phrase is: {0}", response.ReasonPhrase); } } catch (HttpRequestException e) { MessageBox.Show($"\r\nRequest error: {e.Message}"); } catch (Exception e) { MessageBox.Show($"\nException raised: {e.Message}"); } }
关键提醒:
- 绝对不要在无限循环里不加任何等待:哪怕是
Thread.Sleep(1)或者await Task.Delay(1),都能让CPU有时间处理其他任务,避免直接拉满 - 优先用CancellationToken终止任务:替代过时的
Thread.Abort(),避免线程终止时出现不可控的状态 - IO密集型任务优先用异步:HttpClient的异步方法比HttpWebRequest更简洁高效,还能减少线程资源的浪费
内容的提问来源于stack exchange,提问作者user12138044
相关产品推荐
相关产品推荐

