Я работаю над библиотекой C#, которая разгружает определенные рабочие задачи на графический процессор, используя CUDA NVIDIA. Примером этого является добавление двух массивов вместе с использованием методов расширения:Как заблокировать до завершения асинхронного задания
float[] a = new float[]{ ... }
float[] b = new float[]{ ... }
float[] c = a.Add(b);
Работа в этом коде делается на GPU. Тем не менее, я хотел бы, чтобы это выполнялось асинхронно, так что только тогда, когда нужен результат, будет выполняться код на блоке CPU (если результат еще не закончен на графическом процессоре). Для этого я создал класс ExecutionResult, который скрывает асинхронное выполнение. При использовании это выглядит следующим образом:
float[] a = new float[]{ ... }
float[] b = new float[]{ ... }
ExecutionResult res = a.Add(b);
float[] c = res; //Implicit converter
В последней строке программа блокирует, если данные еще готовы. Я не уверен в лучшем способе реализации этого поведения блокировки внутри класса ExecutionResult, так как я не очень разбираюсь в синхронизации потоков и таких вещей.
public class ExecutionResult<T>
{
private T[] result;
private long computed = 0;
internal ExecutionResult(T[] a, T[] b, Action<T[], T[], Action<T[]>> f)
{
f(a, b, UpdateData); //Asych call - 'UpdateData' is the callback method
}
internal void UpdateData(T[] data)
{
if (Interlocked.Read(ref computed) == 0)
{
result = data;
Interlocked.Exchange(ref computed, 1);
}
}
public static implicit operator T[](ExecutionResult<T> r)
{
//This is obviously a stupid way to do it
while (Interlocked.Read(ref r.computed) == 0)
{
Thread.Sleep(1);
}
return result;
}
}
Действие, переданное конструктору, представляет собой асинхронный метод, который выполняет фактическую работу с графическим процессором. Вложенным действием является асинхронный метод обратного вызова.
Моей главной задачей является то, как наилучшим образом/наиболее элегантно обрабатывать ожидания, выполненные в конвертере, но также, если есть более подходящие способы атаки на проблему в целом. Просто оставьте комментарий, если есть что-то, что мне нужно, чтобы уточнить или объяснить дальше.