2015-09-04 3 views
2

У меня есть функция apiClient.OrderSend, которая должна быть вызвана внутри «GUI» нить, поэтому я создал эту функциюПреобразование BeginInvoke в ASync/ждать

private void RunOnUIThread(Action action) 
    { 
     this.BeginInvoke(action); 
    } 

Я тогда функцию, которая должна return в int, как это

int AlgoSendOrder(MT4Order order) 
    { 
     int retVal = -1; 

     RunOnUIThread(() => 
     { 
      retVal = apiClient.OrderSend(order.Symbol, (TradeOperation)order.OrderSide, order.Volume, 
             order.Price, order.AllowedSlippage ?? default(int), 
             order.PriceToStopLoss ?? default(double), 
             order.PriceToTakeProfit ?? default(double)); 
     }); 

     return retVal; 
    } 

проблема заключается в том, что AlgoSendOrder возвращается до того apiClient.OrderSend возвращается, так retVal всегда -1 клиенту этой функции.

Похоже, что это разумное изменение заключается в том, что пара await-async выполняет функцию в потоке графического интерфейса пользователя и имеет желаемый эффект ожидания возвращаемого значения. Однако я не могу заставить его работать.

Похоже, я должен быть в состоянии переработать RunOnUIThread использовать async-await

public async Task RunOnUIThreadAsync() 
{ 
    if (InvokeRequired) 
    { 
     // what do I put here? 
    } 
    { 
     … // like before (but can now use `await` expressions) 
    } 
} 
+0

это WinForm? –

+0

Кажется, что интуитивно понятно, чтобы запустить задачу блокировки (которая занимает много времени) в потоке пользовательского интерфейса. Можно ли запустить вызов API в фоновом режиме и обновить интерфейс отдельно после вызова API? – Onots

+0

@Phillipe, да winform, но вызывающий не гарантированно работает на потоке GUI, следовательно, wrap of begininvoke – Ivan

ответ

6

Используйте метод асинхронного для выполнения фоновой задачи в отдельном потоке. Обратите внимание на Task.Run в образце ниже:

async Task<int> AlgoSendOrderAsync(MT4Order order) 
{ 
    int retVal = -1; 

    //Doing this on another thread using Task.Run 
    await Task.Run(() => 
    { 
     retVal = apiClient.OrderSend(order.Symbol, (TradeOperation)order.OrderSide, order.Volume, 
            order.Price, order.AllowedSlippage ?? default(int), 
            order.PriceToStopLoss ?? default(double), 
            order.PriceToTakeProfit ?? default(double)); 
    }); 

    return retVal; 
} 

вызывать этот метод в потоке пользовательского интерфейса, как это:

async void onButtonClickOnWhatever(object sender, EventArgs args) 
{ 
    int result = await AlgoSendOrderAsync(order); 
    //Here you are on the UI thread, you can update your controls here safely 
}