如果死循环独占线程,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线程?的更多相关文章

  1. 在什么情况下,不写notify()或者notifyAll()就能唤醒被wait()阻塞的线程?

    之前再看java关于线程的某视频时,发现在JDK源码中,join()=join(0)=wait()=wait(0),但是视频中在join()了之后,并没有用notify()或者notifyAll()去 ...

  2. C#.NET使用Task,await,async,异步执行控件耗时事件(event),不阻塞UI线程和不跨线程执行UI更新,以及其他方式比较

    使用Task,await,async,异步执行事件(event),不阻塞UI线程和不跨线程执行UI更新 使用Task,await,async 的异步模式 去执行事件(event) 解决不阻塞UI线程和 ...

  3. 千万别在UI线程上调用Control.Invoke和Control.BeginInvoke,因为这些是依然阻塞UI线程的,造成界面的假死

    原文地址:https://www.cnblogs.com/wangchuang/archive/2013/02/20/2918858.html .c# Invoke和BeginInvoke 区别 Co ...

  4. Qt线程QThread简析(8个线程等级,在UI线程里可调用thread->wait()等待线程结束,exit()可直接退出线程,setStackSize设置线程堆栈,首次见到Qt::HANDLE,QThreadData和QThreadPrivate)

    QThread实例代表一个线程,我们可以重新实现QThread::run(),要新建一个线程,我们应该先继承QThread并重新实现run()函数. 需要注意的是: 1.必须在创建QThread对象之 ...

  5. Qt中运行后台线程不阻塞UI线程的方案

    有一个想法,一个客户端,有GUI界面的同时也要向网络服务器发送本地采集的数据,通过网络发送数据的接口是同步阻塞的,需要等待服务器响应数据. 如果不采用后台线程的方案,用主UI线程关联一个定时器QTim ...

  6. jquery中的ajax请求,阻塞ui线程的解决方案(自己总结的demo)

    /*****************************************************/ function getAjaxData(url,data){ showLoading( ...

  7. android的AsyncTask.get()方法会阻塞UI线程

    AsyncTask.get()方法, 是有阻塞UI的能力的.

  8. Flutter 避免阻塞ui线程

    import 'dart:async'; import 'dart:isolate'; import 'package:flutter/material.dart'; import 'package: ...

  9. C# 多线程详解 Part.02(UI 线程和子线程的互动、ProgressBar 的异步调用)

           我们先来看一段运行时会抛出 InvalidOperationException 异常的代码段: private void btnThreadA_Click(object sender, ...

  10. jQuery同步Ajax带来的UI线程阻塞问题及解决办法

    俗话说不作死就不会死,今天作死了一回,写了一个比较二逼的函数,遇到了同步Ajax引起的UI线程阻塞问题,在此记录一下. 事情起因是这样的,因为页面上有多个相似的异步请求动作,本着提高代码可重用性的原则 ...

随机推荐

  1. Jenkins从Ubuntu迁移至AlmaLinux问题及相关解决记录

    相关背景 之前在Ubuntu平台上搭建了Jenkins(在Ubuntu机器上使用war包安装Jenkins),现在由于一些需求,需要将系统迁移到AlmaLinux平台.由于AlmaLinux属于Cen ...

  2. 文心一言 VS 讯飞星火 VS chatgpt (157)-- 算法导论12.3 4题

    四.用go语言,删除操作可交换吗?可交换的含义是,先删除 x 再删除 y 留下的结果树与先除 y 再删除 x 留下的结果树完全一样.如果是,说明为什么? 否则,给出一个反例. 文心一言: 在Go语言中 ...

  3. Kernel Memory 入门系列: RAG 简介

    Kernel Memory 入门系列: RAG 简介 开一个新坑,Semantic Kernel系列会在 Release 1.0 之后陆续更新. 当我们有了一定的产品资料或者知识内容之后,自然想着提供 ...

  4. Selenium-ActionChains动作链(针对鼠标、滚轮等操作

    https://www.selenium.dev/documentation/webdriver/actions_api/ 注意:对于滚轮的操作,只支持chrome浏览器,且selenium版本在4. ...

  5. Odoo Windows系统下部署方法

    Windows 系统下 Odoo 环境搭建流程 ① 安装python2.7 安装完成后 在命令行(cmd)输入python 如果不出现内部错误提示则表示环境配置成功    当出现错误时要设置环境变量 ...

  6. jclasslib的安装

    双击安装包打开后点击下一步,然后选择安装的路径. 默认路径,如果c盘有空间不建议更改路径,然后再次点击下一步 依然选择下一步 最后点击完成即可完成安装.现在可以使用啦 注:如果需要安装包,请点击下面链 ...

  7. OpenEuler22.03安装最新版本Docker

    一.环境及问题 操作系统环境如下: 操作系统:OpenEuler 22.03 LTS 安装方式:最小化安装 在操作系统安装完毕如果直接采用dnf或者yum方式安装docker: sudo dnf in ...

  8. Windows Server2016 默认使用英文输入法或默认使用中文输入法

    1.确认是Server2016操作系统及以后版本 2.打开开始菜单"设置"--"时间和语言" 3.添加英文输入法(已存在可以跳过) 找到"区域与语言& ...

  9. Pytest07-pytest.ini配置文件

    1.pytest配置文件 固定名称:pytest.ini 作用域:当前目录及子目录 具体配置功能见下: [pytest] # 01 把命令行参数自动添加到这里 addopts = -s -v --ht ...

  10. 2023年资深C#开发者的思考

    2023年转眼间就这样过掉了,作为一名资深C#的开发员人员,年龄也大了1岁,从最早接触C#开始,算下来已经超过15年以上了,随着工作经验的不断增加,物价不断的飞涨以及家庭支出的不断上涨,工作1份工资已 ...