使用TaskEx.WhenAll()时,使用Async进行多线程处理会出现TypeCasting错误

时间:2012-07-15 00:12:56

标签: c# multithreading async-await

在下面的代码中,我试图在另一个线程中执行一个返回值的方法。但是,它只是不起作用!!!

    public void main()
    {
       lstChapters.DataContext = await TaskEx.WhenAll(LoadChapters());
    }



   //CAN'T use  async in this function, it requires Task<> which
   //Error appears on the code inside []

   public [async Task<object>] Convert(object[] values, Type targetType,
     object parameter, System.Globalization.CultureInfo culture)
   {
      dictChapters data = await IQ_LoadQuranXML.LoadChapters(TypeIndex);
   }




    internal static async Task< IEnumerable<dictChapters>> LoadChapters()
    {
        var element = XElement.Load("xml/chapters.xml");

        Task < IEnumerable < dictChapters >>  something = (Task<IEnumerable<dictChapters>>)  await TaskEx.Run(delegate
        {

        IEnumerable<dictChapters> Chapters =  
           from var in element.Descendants("chapter")
           orderby var.Attribute("index").Value
           select new dictChapters
           {
              ChapterIndex = Convert.ToInt32(var.Attribute("index").Value),
              ChapterArabicName = var.Attribute("name").Value,
              ChapterType = var.Attribute("type").Value,
           };
            return Chapters;}
        );

        return something; //An ERROR on this line
     }

    //Overriding method which does not return IEnumerable type. And it accepts index as integer.
    internal static dictChapters LoadChapters(string chIdx = "0")
    {
        int chIdxInt = Convert.ToInt32(chIdx);
        List<dictChapters> Chapters = (List<dictChapters>)  LoadChapters(); // ERROR is on this line too
        return Chapters.ElementAt(chIdxInt - 1); //index of chapter in the element starts from 0
    }

错误是:

  

无法将类型“System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<iq_main.dictChapters>>”隐式转换为“System.Collections.Generic.IEnumerable<iq_main.dictChapters>”。存在显式转换(您是否错过了演员?)

其他错误是..

  

无法将类型“System.Threading.Tasks.Task<System.Collections.Generic.List<iq_main.dictChapters>>”转换为“System.Collections.Generic.List<iq_main.dictChapters>

当我像return (IEnumerable<dictChapters>) something那样明确地转换“某些东西”时,那么在运行时,我会得到“InvalidCastException”。

2 个答案:

答案 0 :(得分:3)

实际上,您将在此之前获得运行时强制转换错误。问题是您对TaskEx.Run结果的演员表。当您await某事时,Task包装将被删除。

public void main()
{
  lstChapters.DataContext = await LoadChapters();
}

internal static Task<List<dictChapters>> LoadChapters()
{
  return TaskEx.Run(delegate
  {
    var element = XElement.Load("xml/chapters.xml");
    IEnumerable<dictChapters> Chapters =  
        from var in element.Descendants("chapter")
        orderby var.Attribute("index").Value
        select new dictChapters
        {
          ChapterIndex = Convert.ToInt32(var.Attribute("index").Value),
          ChapterArabicName = var.Attribute("name").Value,
          ChapterType = var.Attribute("type").Value,
        };
    return Chapters.ToList();
  });
}

您的代码还存在其他一些问题。请记住,像这样的枚举是懒惰执行。您可能希望return Chapters.ToList();以便在线程池线程上进行XML解析。

答案 1 :(得分:1)

由于你在TaskEx.Run上等待,你有可枚举的回来,而不是任务。

对于你正在做的事情,我建议只将LoadChapters保持为普通/同步代码,然后通过Task.Run调用它,或者按原样调用它。

由于延迟执行,AFAICT您当前的代码实际上没有任何帮助,因为您仍然在同步加载。

主要的Task.WhenAll可以删除,只需等待LoadChapters(或任何异步方法