如何写个死循环,既不独占线程,又不阻塞UI线程?
如果死循环独占线程,500个死循环要占用500个线程,如果死循环不独占线程,500个死循环,用200个线程也行,用20个线程也行,无非是执行的慢点
这样可以把同步操作改写为异步,并且节省线程占用
问个问题:写个Socket服务端,接收数据不准用BeginReceive和ReceiveAsync,只能用Receive,Socket客户端10000个,线程池最大不准超过1000,如何实现?
网上是用Select模型,要维护一个Socket对象列表,如果用下面的代码,可以不用维护Socket对象列表,直接有多少Socket对象,就写多少while(true)
代码:


using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Utils; /**
* 如何写个死循环,既不独占线程,又不阻塞UI线程
*/ namespace test
{
public partial class Form1 : Form
{
private int _n = 0;
private bool _run1 = false;
private bool _run2 = false;
private TaskSchedulerEx _task1 = new TaskSchedulerEx(2, 2); //只给2个线程 public Form1()
{
InitializeComponent();
ThreadPool.SetMaxThreads(12, 12); //最多给12个线程
ThreadPool.SetMinThreads(10, 10);
} private void Form1_Load(object sender, EventArgs e)
{ } /// <summary>
/// 测试1
/// 现象:会输出i=5,也会输出i=15,button3有事件响应,因为20个死循环,2个线程也能处理,只不过处理速度慢,加大线程池容量可加快处理速度
/// </summary>
private void button1_Click(object sender, EventArgs e)
{
_n = 0;
button1.Enabled = false;
button2.Enabled = true;
_run1 = true;
_run2 = false;
textBox1.Text = string.Empty;
for (int i = 1; i <= 20; i++) //启动20个死循环
{
_task1.Run(async (obj) => //用_task1(只给2个线程)启动20个死循环
{
dynamic var = (dynamic)obj; while (_run1) //此while不会独占线程
{
Task t = Task.Factory.StartNew(() =>
{
Thread.Sleep(100);
Interlocked.Increment(ref _n); if (var.i == 5 || var.i == 15)
{
int a1; int a2; int m1; int m2;
ThreadPool.GetMaxThreads(out m1, out a1);
ThreadPool.GetAvailableThreads(out m2, out a2);
Log("当前使用辅助线程数:" + (m1 - m2) + ",当前使用异步线程数:" + (a1 - a2) + ",i=" + var.i + ",n=" + _n);
}
});
await t;
}
}, new { i = i });
}
} /// <summary>
/// 测试2
/// 现象:只输出i=5,不输出i=15,button3不能响应事件,因为有20个死循环,12个线程不够用,但因为12个线程比较多,所以处理速度较快
/// </summary>
private void button2_Click(object sender, EventArgs e)
{
_n = 0;
button1.Enabled = true;
button2.Enabled = false;
_run1 = false;
_run2 = true;
textBox1.Text = string.Empty;
for (int i = 1; i <= 20; i++) //启动20个死循环
{
Task.Factory.StartNew((obj) => //用Task(最多12个线程)启动20个死循环
{
dynamic var = (dynamic)obj; while (_run2) //此while会独占一个线程
{
Thread.Sleep(100);
Interlocked.Increment(ref _n); if (var.i == 5 || var.i == 15)
{
int a1; int a2; int m1; int m2;
ThreadPool.GetMaxThreads(out m1, out a1);
ThreadPool.GetAvailableThreads(out m2, out a2);
Log("当前使用辅助线程数:" + (m1 - m2) + ",当前使用异步线程数:" + (a1 - a2) + ",i=" + var.i + ",n=" + _n);
}
}
}, new { i = i });
}
} private void button3_Click(object sender, EventArgs e)
{
Task.Factory.StartNew(() =>
{
Log("button3_Click 有响应"); //测试button3是否能响应事件
});
}
}
}
使用async、await异步之后,就更好写了,非常优雅:


private async void button2_Click(object sender, EventArgs e)
{
while (true) // 死循环,但不阻塞UI线程
{
if (!this.IsDisposed)
{
textBox1.AppendText("测试\r\n");
} await Task.Delay(500);
}
}
如何写个死循环,既不独占线程,又不阻塞UI线程?的更多相关文章
- 在什么情况下,不写notify()或者notifyAll()就能唤醒被wait()阻塞的线程?
之前再看java关于线程的某视频时,发现在JDK源码中,join()=join(0)=wait()=wait(0),但是视频中在join()了之后,并没有用notify()或者notifyAll()去 ...
- C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较
使用Task,await,async,异步执行事件(event),不阻塞UI线程和不跨线程执行UI更新 使用Task,await,async 的异步模式 去执行事件(event) 解决不阻塞UI线程和 ...
- 千万别在UI线程上调用Control.Invoke和Control.BeginInvoke,因为这些是依然阻塞UI线程的,造成界面的假死
原文地址:https://www.cnblogs.com/wangchuang/archive/2013/02/20/2918858.html .c# Invoke和BeginInvoke 区别 Co ...
- Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)
QThread实例代表一个线程,我们可以重新实现QThread::run(),要新建一个线程,我们应该先继承QThread并重新实现run()函数. 需要注意的是: 1.必须在创建QThread对象之 ...
- Qt中运行后台线程不阻塞UI线程的方案
有一个想法,一个客户端,有GUI界面的同时也要向网络服务器发送本地采集的数据,通过网络发送数据的接口是同步阻塞的,需要等待服务器响应数据. 如果不采用后台线程的方案,用主UI线程关联一个定时器QTim ...
- jquery中的ajax请求,阻塞ui线程的解决方案(自己总结的demo)
/*****************************************************/ function getAjaxData(url,data){ showLoading( ...
- android的AsyncTask.get()方法会阻塞UI线程
AsyncTask.get()方法, 是有阻塞UI的能力的.
- Flutter 避免阻塞ui线程
import 'dart:async'; import 'dart:isolate'; import 'package:flutter/material.dart'; import 'package: ...
- C# 多线程详解 Part.02(UI 线程和子线程的互动、ProgressBar 的异步调用)
我们先来看一段运行时会抛出 InvalidOperationException 异常的代码段: private void btnThreadA_Click(object sender, ...
- jQuery同步Ajax带来的UI线程阻塞问题及解决办法
俗话说不作死就不会死,今天作死了一回,写了一个比较二逼的函数,遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下. 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则 ...
随机推荐
- Codeforces Round #706 (Div. 2) A-D题解
写在前边 链接:Codeforces Round #706 (Div. 2) \(A,B,C,D\),这场有点简单,不过由于A写炸了后边题连看都没看就溜了,就从上大分变成了掉大分 A. Split i ...
- Ubuntu 18.04替换默认软件源
安装Ubuntu 18.04后,默认源在国外,可以替换为国内的源以提升访问速度 参考https://mirrors.ustc.edu.cn/repogen/ sudo vi /etc/apt/sour ...
- GitHub Desktop安装与使用教程
一.安装 1.下载 下载地址 2.安装 下载之后GitHub Desktop是没有安装步骤的,而是开始安装之后,稍等片刻就安装成功了. 然后登陆个人GitHub账号就可以进行一下操作了. 二.新建仓库 ...
- MySQL8.0 安装教程
一.下载 1.官网地址 MySQL :: Download MySQL Community Server 2.选择安装包安装方式 3.选择安装版本 4.开始下载 5.下载成功 二.安装 1.双击安装包 ...
- Vue-cli脚手架下载安装
注意:在下载安装该脚手架之前先安装配置好NodeJS以及镜像源,NodeJS详情可查询文章:NodeJS下载安装 1.cmd中输入以下指令: npm install -g @vue/cli 整个过程中 ...
- 【eBPF-01】初见:基于 BCC 框架的第一个 eBPF 程序
闲言少叙,本文记录了如何零基础通过 BCC 框架,入门 eBPF 程序的开发,并实现几个简易的程序. 有关 eBPF 的介绍,网络上的资料有很多,本文暂且先不深入讨论,后面会再出一篇文章详细分析其原理 ...
- 学透java自增(++)自减(--)运算符
基本介绍 自增(++)和自减(--)运算符是对变量在原始值的基础上进行加1或减1的操作. 它们都有前缀和后缀两种形式. 前缀就是++在前面,后缀就是++在后面 前缀先自增(减),后缀后自增(减) 前缀 ...
- 交换机SNMP配置
配置参考v2c为例 1.华为 snmp-agent protocol source-interface vlanif 1 ##S573x以上型号交换机需要snmp-agentsnmp-agent sy ...
- Java 中时间对象的序列化
在 Java 应用程序中,时间对象是使用地比较频繁的对象,比如,记录某一条数据的修改时间,用户的登录时间等应用场景.在传统的 Java 编程中,大部分的程序员都会选择使用 java.uti.Date ...
- 中国汽车工业协会 SDV 软件定义汽车服务 API 第三版下载
开门见山,下载链接: https://files.cnblogs.com/files/tengzijian/SDV_API_Version3_Beta1_公众号:好记性如烂笔头.zip?t=16904 ...