之前在写C#多线程,多并发操作的时候,一直都用Thread来实现的,但是发现有一个问题,就是用Thread的话,如果暂时没有要处理的数据,会多条线程一直在空转。最近学了SemaphoreSlim信号量后,发现这个玩意用起来比较舒服。只需要确定一下最大的并发数,就可以自动调控了。也不会出现空转的情况。
这个是效果图。演示从1到1万循环,并且开n个并发。下面是测试代码。大家可以自行参考一下。
namespace 信号量并发测试
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// 最大并发
const int MaxConcurrency = 500;
SemaphoreSlim semaphore = new SemaphoreSlim(MaxConcurrency);
int index = 0;
private async void button1_Click(object sender, EventArgs e)
{
index = 0;
listBox1.Items.Clear();
button1.Enabled = false;
try
{
await RunTask();
}
catch (Exception ex)
{
MessageBox.Show($"测试出错:{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
finally
{
button1.Enabled = true;
}
}
private async Task RunTask()
{
var tasks = new List<Task>();
while (true)
{
int num = Interlocked.Increment(ref index);
if (num > 10000)
{
break;
}
await semaphore.WaitAsync();
this.BeginInvoke(() =>
{
label1.Text = $"并发:{MaxConcurrency - semaphore.CurrentCount}/{MaxConcurrency}";
});
Task t = Task.Run(async () =>
{
try
{
this.BeginInvoke(() =>
{
listBox1.Items.Insert(0, $"数字:{num} 时间:{DateTime.Now:HH:mm:ss.fff}");
});
await Task.Delay(300); // 模拟异步耗时
}
finally
{
semaphore.Release();
this.BeginInvoke(() =>
{
label1.Text = $"并发:{MaxConcurrency - semaphore.CurrentCount}/{MaxConcurrency}";
});
}
});
tasks.Add(t);
}
await Task.WhenAll(tasks);
}
private void button2_Click(object sender, EventArgs e)
{
button2.Enabled = false;
var threads = new List<Thread>();
index = 0;
for (int i = 0; i < MaxConcurrency; i++)
{
Thread t = new Thread(() =>
{
while (true)
{
int num = Interlocked.Increment(ref index);
if (num > 10000)
{
break;
}
this.BeginInvoke((Delegate)(() =>
{
listBox1.Items.Insert(0, $"数字:{num} 时间:{DateTime.Now:HH:mm:ss.fff}");
}));
Thread.Sleep(300); // 模拟耗时
}
});
t.Start();
threads.Add(t);
}
foreach (var t in threads)
{
t.Join();
}
button2.Enabled = true;
}
}
}


小菜鸟
学习了。