События - асинхронны? Как затормозить обработчик события так, чтобы не остановить все остальное?
У меня есть два класса, которые общаются с помощью событий. Обработчик события в классе Bot, которое приходит из внешнего источника:
private void OnOrder(Order order)
{
if (order.Account == Tool.AccountID && order.SecCode == Tool.SecurityCode && order.State == State.Completed)
{
Task.Delay(50); // здесь нужно подождать
Strategy.ProcessingExecutedOrders(order);
}
}
Метод в классе Bot, в котором вызывается событие NewDeal:
private void SendOrders(ref Deal deal)
{
// что-то происходит
// асинхронный метод, после которого может прийти событие OnOrder, а может и не прийти
temp_order = QuikConnecting.LimitOrder(Tool, deal.OrdersInfo[i].Operation, deal.OrdersInfo[i].Price, deal.OrdersInfo[i].Vol).Result;
if (temp_order != null)
{
deal.OrdersInfo[i].IDOrder = temp_order.OrderNum;
deal.OrdersInfo[i].IssueStatus = State.Completed;
deal.Status = StatusDeal.Open;
NewDeal?.Invoke(deal, Command.SendOrder); // вызываю другое событие, которое передает объект в другой класс
}
// что-то происходит
}
Проблема в том, что событие OnOrder может прийти раньше, чем произойдет NewDeal?.Invoke. И мне нужно чтобы OnOrder ждал хоть какое-то время, но Task.Delay не работает. В связи с этим вопрос, как тормознуть обработчик события OnOrder так, чтобы метод SendOrders продолжил работать?
Ответы (1 шт):
Вот эту цитату от @tym32167 надо высечь в камне.
Если в вашей системе из двух классов порядок независимых друг от друга событий начал играть роль и вы начали добавлять какие то тайминги в код, то вы что то явно делаете не так.
Если вопрос только про ожидание, то у вас всего 2 опции ожидания:
- Синхронное
private void OnOrderAsync(Order order)
{
if (order.Account == Tool.AccountID && order.SecCode == Tool.SecurityCode && order.State == State.Completed)
{
Thread.Sleep(50);
Strategy.ProcessingExecutedOrders(order);
}
}
- Асинхронное
private async Task OnOrder(Order order)
{
if (order.Account == Tool.AccountID && order.SecCode == Tool.SecurityCode && order.State == State.Completed)
{
await Task.Delay(50);
Strategy.ProcessingExecutedOrders(order);
}
}
Разница в том, что первое блокирует вызывающий поток на время ожидания, в второе - нет.
Как вы уже наверное поняли, вы просто неправильно использовали Task.Delay.
Так же у вас ошибка в использовании асинхронной операции, вы ее вызываете синхронно, что в принципе противоречит принципам асинхронности
// делаем метод асинхронным - вызывать так: await SendOrdersAsync(...);
private async Task SendOrdersAsync(ref Deal deal)
{
// ...
temp_order = await QuikConnecting.LimitOrder(Tool, deal.OrdersInfo[i].Operation, deal.OrdersInfo[i].Price, deal.OrdersInfo[i].Vol);
if (temp_order != null)
{
deal.OrdersInfo[i].IDOrder = temp_order.OrderNum;
deal.OrdersInfo[i].IssueStatus = State.Completed;
deal.Status = StatusDeal.Open;
NewDeal?.Invoke(deal, Command.SendOrder);
}
// ...
}
Никогда не используйте .Wait() или .Result для асинхронных операций. Это ошибка, которая 1) вешает вам поток, 2) может привести к взаимоблокировке потоков - дедлоку.
Неисключено, что после того как вы поправите ошибку вызова асинхронного метода, ваши события заработают как надо, и не придется втыкать костыли типа Task.Delay.
Почитайте: Асинхронное программирование.