gpt4 book ai didi

c# - 在 LINQ 中调用 Task<> 方法并返回数据

转载 作者:太空宇宙 更新时间:2023-11-03 21:33:13 24 4
gpt4 key购买 nike

我在调用 Task<> 时遇到问题LINQ 语句中的方法并尝试从 Task<> 返回数据(图像)方法。我无法获得 Task<>返回数据(图像)的方法,我收到以下错误:

Cannot implicitly convert type 'System.Threading.Tasks.Task' to 'System.Uri'.

这是带有 LINQ 语句的 DownloadStringCompleted 方法,我在其中调用 GetTest Task<> 方法:

private async void GetGamesListRequestCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
var feedXml = XDocument.Parse(e.Result);

var gameData = feedXml.Root.Descendants("Game").Select(x => new GetGamesList
{
ID = (int)x.Element("id"),
GameTitle = (string)x.Element("GameTitle"),
ReleaseDate = (string)x.Element("ReleaseDate"),
Platform = (string)x.Element("Platform"),
Front = GetTest((int)x.Element("id")), // THE METHOD WITH PROBLEM.
})
.ToList();

foreach (var item in gameData)
{
GetGamesListItems.Add(item);
}
}
}

我在尝试返回数据(图像)时遇到问题的 Task<> GetTest 方法:

public Task<string> GetTest(int id)
{
var tcs = new TaskCompletionSource<string>();
var client = new WebClient();
client.DownloadStringCompleted += (s, e) =>
{
if (e.Error == null)
{
var feedXml = XDocument.Parse(e.Result);

var gameData = feedXml.Root.Descendants("Images").Select(x => new GetArt
{
BoxArtFrontThumb = new Uri(GetBoxArtFront(x)),
})
.ToList();

foreach (var item in gameData) GetArtItems.Add(item);
foreach (var i in GetArtItems)
{
tcs.SetResult("http://thegamesdb.net/banners/" + i.BoxArtFrontThumb.ToString());
}
}
else
{
tcs.SetException(e.Error);
}
};

client.DownloadStringAsync(new Uri("http://thegamesdb.net/api/GetArt.php?id=" + id.ToString()));
return tcs.Task;
}

我存储图像的 ObservableCollection: 私有(private) ObservableCollection _GetArtItems = new ObservableCollection();

public ObservableCollection<GetArt> GetArtItems
{
get
{
return this._GetArtItems;
}
}

我从 XML 获取图像的位置:

private static string GetBoxArtFront(XElement gameNode)
{
return "http://thegamesdb.net/banners/" + (string)gameNode.Descendants("boxart")
.FirstOrDefault(b => (string)b.Attribute("side") == "front");
}

这是我用来存储数据(图像)的类:

public class GetArt
{
public Uri BoxArtFrontThumb { get; set; }
}

这是我的 LongListSelector,我想在其中显示数据(图像):

<phone:LongListSelector Name="llsGameList" Background="#242424" ItemsSource="{Binding}" Tap="llsGameList_Tap" Margin="0,90,0,0">
<phone:LongListSelector.ItemTemplate>
<DataTemplate>
<Grid>
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu Name="ContextMenu">
<toolkit:MenuItem
Name="addToFavorite"
Header="Add to favorite"
Click="addToFavorite_Click"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
<StackPanel>
<Border Background="{StaticResource PhoneAccentBrush}"
Padding="{StaticResource PhoneTouchTargetOverhang}"
Margin="{StaticResource PhoneTouchTargetOverhang}">
<TextBlock Name="tblGameTitle" Style="{StaticResource PhoneTextGroupHeaderStyle}" ManipulationStarted="tblGameTitle_ManipulationStarted" ManipulationCompleted="tblGameTitle_ManipulationCompleted">
<Run Text="{Binding GameTitle}"></Run>
</TextBlock>
</Border>
<Image Source="{Binding Front}" Height="200" Width="200"></Image> // HERE IM BINDING TO MY FRONT PROPERTY TO SHOW THE IMAGES
<TextBlock TextWrapping="Wrap" Foreground="YellowGreen" Style="{StaticResource PhoneTextNormalStyle}" Padding="{StaticResource PhoneTouchTargetOverhang}"
FontSize="{StaticResource PhoneFontSizeNormal}">
<Run Text="Platform: "></Run>
<Run Text="{Binding Platform}"></Run>
</TextBlock>
<TextBlock Foreground="YellowGreen" Style="{StaticResource PhoneTextNormalStyle}" Padding="{StaticResource PhoneTouchTargetOverhang}"
FontSize="{StaticResource PhoneFontSizeNormal}">
<Run Text="Release Date: "></Run>
<Run Text="{Binding ReleaseDate}"></Run>
</TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
</phone:LongListSelector.ItemTemplate>
</phone:LongListSelector>

这是我的 DataContext,它获取 gd.GetGamesListItems,其中包含我想在 LongListSelector 中显示的图像:

public MainPage()
{
InitializeComponent();
llsGameList.DataContext = gd.GetGamesListItems;
}

我希望有人可以帮助我 :)。谢谢。

最佳答案

每当你有一个Task<T> ,您需要花一些时间考虑您希望如何(异步)等待结果。请记住,一个 Task<T>表示 future 结果,而不是当前结果。

一个选项是根据@Sriram 的回答,它将(异步地)一次等待一个结果,并在它们到达时将它们添加到列表中。另一种选择是做这样的事情:

var feedXml = XDocument.Parse(e.Result);
var gameDataTasks = feedXml.Root.Descendants("Game").Select(
async x => new GetGamesList
{
ID = (int)x.Element("id"),
GameTitle = (string)x.Element("GameTitle"),
ReleaseDate = (string)x.Element("ReleaseDate"),
Platform = (string)x.Element("Platform"),
Front = new Uri(await GetTestAsync((int)x.Element("id"))),
}).ToList();
var gameData = await Task.WhenAll(gameDataTasks);
foreach (var item in gameData)
{
GetGamesListItems.Add(item);
}

这将启动所有 GetTestAsync调用所有元素,然后(异步地)等待它们全部完成(并检索结果)。

其他说明:

  • 我确实将您的方法重命名为 GetTestAsync符合 Task-based Asynchronous Pattern .
  • 我发现如果使用较新的 HttpClient,代码会更简洁,内置支持 await .

这是一个使用 HttpClient 的例子:

public async Task<string> GetTestAsync(int id)
{
var client = new HttpClient();
var result = await client.GetStringAsync("http://thegamesdb.net/api/GetArt.php?id=" + id);
var feedXml = XDocument.Parse(result);
var gameData = feedXml.Root.Descendants("Images").Select(x => new GetArt
{
BoxArtFrontThumb = new Uri(GetBoxArtFront(x)),
}).ToList();
foreach (var item in gameData) GetArtItems.Add(item);
return "http://thegamesdb.net/banners/" + gameData.Single().BoxArtFrontThumb.ToString()
}

关于c# - 在 LINQ 中调用 Task<> 方法并返回数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23152509/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com