当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - Multithreading with Async gives a TypeCasting Error when using TaskEx.WhenAll()

问题描述:

In the code below, I am trying to execute a method, which returns a value, in another thread. However, it just DOES NOT work!!!

 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

}

The Error is:

Cannot implicitly convert type 'System.Threading.Tasks.Task<System.Collections.Generic.IEnumerable<iq_main.dictChapters>>' to 'System.Collections.Generic.IEnumerable<iq_main.dictChapters>'. An explicit conversion exists (are you missing a cast?)

And the Other error is..

Cannot convert type 'System.Threading.Tasks.Task<System.Collections.Generic.List<iq_main.dictChapters>>' to 'System.Collections.Generic.List<iq_main.dictChapters>

When I cast "something" explicitly like return (IEnumerable<dictChapters>) something then at runtime, I get "InvalidCastException".

网友答案:

Actually, you'll be getting a runtime cast error earlier than that. The problem is your cast of the TaskEx.Run result. When you await something, the Task wrapper is removed.

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

There are a few other problems with your code as well. Remember that enumerations like this are lazily executed. You probably want to return Chapters.ToList(); so that the XML parsing happens on the thread pool thread.

网友答案:

Since you did await on the TaskEx.Run, you have the enumerable coming back, not a task.

For what you're doing, I'd recommend just keeping LoadChapters as normal/sync code, then either just invoke it via Task.Run, or call it as-is.

Due to deferred execution, AFAICT your current code doesn't really help anything since you're still doing the Load synchronously.

The Task.WhenAll in main could be removed, just await LoadChapters (or whatever the asynchronous method is

分享给朋友:
您可能感兴趣的文章:
随机阅读: