并行性和异步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倍async(视频变量的值(,如果两个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;
}

最新更新