c# - 并行和异步 C#
问题描述
我正在用 C# 编写一个控制台应用程序,它需要一组视频并对其进行转码,只要新的 GPU 可以免费使用。运行应用程序的机器有两个 GPU。但我真的很难建立这个。完成这项工作的方法是FireTranscode()
private void FireTranscode(int counter)
{
Random rand = new Random();
int gpu;
lock (thisLock)
{
gpu = PickGPU(0) == true ? 0 : 1;
GPU[gpu] = false;
if (gpu == 0) { gpuZero += 1; } else { gpuOne += 1; };
Thread.Sleep(rand.Next(1, 5));
videos -= 1;
}
Console.WriteLine($"Transconding on {gpu} using thread: {Thread.CurrentThread.ManagedThreadId} {transcodeArray[Convert.ToInt32(counter), 2]}");
GPU[gpu] = true;
}
它由 ManageTranscode() 触发
private async void ManageTrancode()
{
for(counter=0; counter < videos; counter++)
{
if (GPU[0] == false & GPU[1] == false)
{
await Task.WhenAny(transcodeList);
}
else
{
transcodeList.Add(Task.Factory.StartNew(() => FireTranscode(counter)));
}
}
}
它假设调用 FireTranscode 后跟参数计数器,40 次异步(视频变量的值),并且如果两个 GPU(static Dictionary<int, bool> GPU = new Dictionary<int, bool> { { 0, true }, { 1, true } };
都在使用中(=false)它应该等到任何任务完成并免费使用(=true) .
我正在尝试学习如何正确使用它,我将不胜感激一些提示并帮助实现这一目标。谢谢你。
解决方案
通过使用以下代码,您可以简化逻辑并使其在可用 GPU 方面更具可扩展性。它使用SemaphoreSlim
(@Poul Bak 也提到)允许通过定义的参数实现并行度。
此外,我已重构您的代码以将 GPU 作为类(您也可以使用 Struct)。
private object lockObj = new object();
private List<GPU> availableGPUs = List<GPU>() { /* initialize GPUs here */};
private int AvailableGPUCount { get { return availableGPUs.Count(); } }
private async void ManageTrancode()
{
int maxThread = AvailableGPUCount;
SemaphoreSlim lockSlim = new SemaphoreSlim(maxThread, maxThread);
for(int counter = 0; counter < videos; counter++)
{
await lockSlim.WaitAsync();
await Trancode();
lockSlim.Release();
}
}
private async Task Trancode()
{
GPU gpu = GetAndLockGPU();
// await <<Run actual trancode here>>
ReleaseGPU(gup.Id);
}
private GPU GetAndLockGPU()
{
GPU gpu = null;
lock (lockObj)
{
gpu = availableGPUs.First(g => g.IsAvailable);
gpu.IsAvailable = false;
}
return gpu;
}
private void ReleaseGPU(int gpuId)
{
lock (lockObj)
{
availableGPUs.First(g => g.Id == gpuId).IsAvailable = true;
}
}
private class GPU
{
public int Id {get; set;}
public bool IsAvailable {get; set;} = true;
}
推荐阅读
- php - 使用日期助手指定月份或 Laravel/Eloquent 问题?
- node.js - CouchDB 整数大小
- javascript - 单击最近的输入时一次仅显示一个跨度
- c# - 我如何也可以使用 httpclient 创建一个功能,即使在应用程序关闭完成后也能保持用户登录?
- r - 数据表 R - 聚合
- admin - 为新开发人员推荐的博客主机是什么?
- c++ - 安全 SSL 连接错误:未知协议 | 错误的主机名查找
- css - Internet Explorer 上的 Angular 6 -- Angular Material/Flex 布局不会居中?
- javascript - 如果字符串中包含特定单词,则删除该单词
- sql-server - 查询不符合 XML 的结构化数据