在C#中,如何知道外部服务何时完成回调?

时间:2017-01-25 00:54:57

标签: c# asynchronous callback service-reference

我的.NET 控制台应用程序中有一个外部引用,可以为我提供大字符串的语言翻译。

在循环中,我对服务进行了一系列调用。总共可能有5000-8000个电话。

该服务要求我实现一个回调函数,以便在完成工作时它可以将已翻译的字符串返回给我。在另一个继承了TranslationService接口的类中,我实现了它们的回调函数:

class MyTranslationServiceCallback : TranslationService.ITranslationServiceCallback
{
    public void TranslateTextCallback(string sourceContent, string responseContent)
    {
        UpdateMyDatabase(responseContent);
    }
}

调试时,我在Console.Readkey的最后添加了Main(),以防止应用程序关闭,以便完成所有回调。到目前为止,我刚刚假设当它停止进入回调函数一分钟左右时它已经完成了#34; (我知道,这很糟糕)。

所以看起来像:

class Program
{
    static void Main(string[] args)
    {
        foreach (var item in itemList)
        {
            TranslationService.TranslateText(item.EnglishText, "french");
        }

        Console.Readkey()
    }
}

确定所有回调是否已完成的正确方法是什么?

3 个答案:

答案 0 :(得分:1)

由于翻译服务无法告知翻译状态,因此您需要跟踪所做的调用和回调。创建一个具有计数器并在每次调用时递增的单例。减少每次回叫的计数。

答案 1 :(得分:0)

为什么不使用.NET内置的异步框架?您需要做的就是触发任务并在数组中跟踪它们,然后您可以调用Task.WhenAll来阻止程序直到所有任务都完成。

注意:我正在使用Nito.AsyncEx NuGet包,以便从控制台应用运行异步代码。

class Program
    {
      static int Main(string[] args)
      {
        return AsynContent.Run(() => MainAsync(args));
      }

      static async Task<int> MainAsync(string[] args)
      {
        var taskList = new List<Task>();

        foreach (var item in itemList)
        {
          Task.Factory.StartNew(() => TranslationService.TranslateText(item.EnglishText, "french");
        }

        Task.WhenAll(taskList.ToArray());
      }
}

答案 2 :(得分:0)

如果您在.NET中实现此功能,那么async / await就是您的朋友。

如果不是通过回调返回结果,TranslationService返回Task<string>,那就太棒了。

然后你可以实现以下内容:

static async Task TranslateAllItems(IEnumerable<Item> list)
{
     foreach(var item in itemList)
     {
         string result = await TranslationService.TranslateText(item.EnglishText, "french");
         UpdateMyDatabase(item.EnglishText, content);
     }
}

static void Main(string[] args)
{
    Task task = TranslateAllItems(itemList);
    task.Wait();
    Console.ReadKey();
}

上述解决方案将按顺序执行每个翻译,等待一个翻译任务完成,然后再开始下一个翻译任务。

如果启动所有翻译会更快,那么等待整个批次完成:

static Task TranslateAllItems(IEnumerable<Item> list)
{
     List<Task> waitingTasks = new List<Task>();
     foreach(var item in itemList)
     {
          string englishText = item.EnglishText;
          var task = TranslationService.TranslateText(englishText , "french")
              .ContinueWith(taskResult => UpdateMyDatabase(englishText, taskResult.Result);
          waitingTasks.Add(task);
     }
     return Task.WhenAll(waitingTasks);
 }