【问题标题】:Convert BeginInvoke to async/await将 BeginInvoke 转换为 async/await
【发布时间】:2016-04-29 05:56:50
【问题描述】:

我有一个函数apiClient.OrderSend 必须在“GUI”线程内调用,所以我创建了这个函数

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

然后我有一个函数需要像这样 returnint

    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;
    }

问题是AlgoSendOrderapiClient.OrderSend返回之前返回,所以retVal对于这个函数的客户端总是-1。

看来这个合理的改变是使用await-async对在GUI线程中执行函数,并达到预期的等待返回值的效果。但是我似乎无法让它工作。

看来我应该可以重做RunOnUIThread 以使用async-await

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

【问题讨论】:

  • 在 UI 线程上运行阻塞任务(需要很长时间)似乎违反直觉。是否可以在后台运行 API 调用并在 API 调用返回后单独更新 UI?
  • @Phillipe,是的 winform,但调用者不能保证在 GUI 线程上,因此 begininvoke 的包装
  • @Onots,没有 apiclient.OrderSend 在 GUI 线程外崩溃。此外,整个过程不到 1 毫秒。

标签: c# winforms async-await begininvoke


【解决方案1】:

使用异步方法在单独的线程中执行后台任务。请注意以下示例中的 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;
}

像这样在 UI 线程上调用这个方法:

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
}

【讨论】:

    猜你喜欢
    • 2014-02-16
    • 1970-01-01
    • 2019-08-11
    • 2019-11-08
    • 1970-01-01
    • 2012-10-25
    • 1970-01-01
    • 2021-10-19
    • 2021-04-10
    相关资源
    最近更新 更多