Похоже, проблема, с которой вы сталкиваетесь, связана с тем, что таймер вызывает функцию во второй раз до завершения первого вызова. Согласно документации, ваша установка таймера будет вызывать функцию обратного вызова таймера каждые 100 миллисекунд, однако она не будет ждать выполнения предыдущего запуска (для ее запуска в моей системе требуется 1,3 секунды для первой итерации и ~ 650 мс для последующих вызовов).
HybRunner не является поточно-ориентированным. Также обратите внимание, что контекст CUDA присоединен к потоку, а для использования другого потока требуется другой контекст CUDA.
Вот альтернативная реализация для решения вашей проблемы с использованием рабочего потока, который выполняет задачи, связанные с графическим процессором:
Сначала объявите компоненты синхронизации:
static bool workerrunning = false;
static object started = new object();
static Queue<object> tasks = new Queue<object>();
static object watch = new object();
Рабочий поток l oop может быть следующим:
public static void HybridLoop(object p)
{
lock (started)
{
workerrunning = true;
Monitor.Pulse(started);
}
while (workerrunning)
{
object currenttask = null;
// get next task
lock (watch)
{
if (tasks.Count == 0)
{
Monitor.Wait(watch);
}
if (tasks.Count != 0)
{
currenttask = tasks.Dequeue();
// NOTE: here, we illustrate more tasks than doable => clear
tasks.Clear();
}
}
if (currenttask != null)
{
gpuDllTest.Test("GPU_DLL_CUDA.dll");
}
}
}
Здесь мы очищаем очередь задач, поскольку она заполняется быстрее, чем потребляется.
Код для запуска рабочего потока:
System.Threading.Thread hybridrunner = new System.Threading.Thread(HybridLoop);
lock(started)
{
hybridrunner.Start();
Monitor.Wait(started);
}
Как только рабочий запущен, таймер может быть запущен:
System.Timers.Timer tmr = new System.Timers.Timer(100);
tmr.Elapsed += Tmr_Elapsed;
tmr.Start();
Console.Out.WriteLine("Runner started - press return to stop");
var key = Console.Read();
Ваша функция истечения таймера - просто задание задачи:
private static void Tmr_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
lock (watch)
{
tasks.Enqueue(1);
Monitor.Pulse(watch);
}
}
После выполнения бегун может быть остановлен, чтобы избежать запуска хвостового потока:
workerrunning = false;
lock (watch)
{
tmr.Stop();
tasks.Enqueue(0);
Monitor.Pulse(watch);
}
Console.Out.WriteLine("Runner stopping");
hybridrunner.Join();
Console.Out.WriteLine("Runner stopped");
Пример журнала выполнения:
DONE
Execution took 1026 milliseconds
DONE
Execution took 642 milliseconds
DONE
Execution took 614 milliseconds
Runner started - press return to stop
DONE
DONE
DONE
Runner stopping
DONE
Runner stopped
В качестве последнего примечания вы можете выполнить некоторую инициализацию, такую как HybRunner.Cuda (), только один раз, а затем выполнять другие задачи в том же рабочем потоке.