【问题标题】:System Threading Tasks String To String Conversion Error系统线程任务字符串到字符串转换错误
【发布时间】:2019-07-31 06:55:18
【问题描述】:

我正在尝试根据 CandidateID 将 Firebase 上的照片下载到列表视图中。

我有一个任务列表链接为列表视图的数据源和一个从 firebase 检索 URL 的函数。

我试图在任务列表中添加一个字符串以检索 URL,但我收到一条错误消息,提示我无法将 system.threading.tasks 字符串转换为字符串。

    public async Task<string> GetFile(string fileName)
    {      
        return await GlobalVar.firebaseStorage
            .Child("ProfilePhotos")
            .Child(fileName)
            .GetDownloadUrlAsync();
    }

    public async Task<List<JobApplication>> GetApplications()
    {
        var canInfo = await GetCandidates();
        return (await GlobalVar.firebaseClient
          .Child("JobApplication")
          .OnceAsync<JobApplication>()).Select(item => new JobApplication
          {

              CandidateID = item.Object.CandidateID,
              ApplicationDate = item.Object.ApplicationDate,
              ApplicationTime = item.Object.ApplicationTime,
              CandidateName = canInfo.Find(a => a.CandidateId == item.Object.CandidateID).Name + " " + canInfo.Find(a => a.CandidateId == item.Object.CandidateID).LastName,
              NewCanID = item.Object.CandidateID.Substring(1),
              ImageURL = GetFile(item.Object.CandidateID.Substring(1) + "-One.jpg")
          }).ToList();
    }

我在 Image Source 中使用了 Eval 表达式,但在 'GetFile(item.Object.CandidateID.Substring(1) + "-One.jpg")' 下有一条红线。无论如何我可以将其转换为有效的字符串以便它可以工作吗?

【问题讨论】:

  • 我尝试在 GetFile 之前使用 await,但它说它只能用于异步 lambda 表达式。如果我在没有返回 URL 之后尝试 ToString()。
  • 好的 ImageURL = Task.Run(() => GetFile(item.Object.CandidateID.Substring(1) + "-One.jpg")).Result 似乎有效,但如果没有它抛出一个错误的文件。无论如何要抓住这个?

标签: c# asp.net visual-studio firebase asynchronous


【解决方案1】:

我收到一条错误消息,提示我无法将 system.threading.tasks 字符串转换为字符串。

Visual Studio 给你这个错误是因为你试图将 Task&lt;string&gt; 分配给 string,但它找不到转换。 Task&lt;T&gt; 包裹了 T,您需要解开 T。从Task&lt;T&gt; 解包T 的正确方法是使用await

在这种情况下,我认为分解那个巨大的return 语句更容易,然后你可以更清楚地看到你需要做什么:

public async Task<List<JobApplication>> GetApplications()
{
  var canInfo = await GetCandidates();
  var jobApplication = await GlobalVar.firebaseClient
          .Child("JobApplication")
          .OnceAsync<JobApplication>();
  return jobApplication.Select(item => new JobApplication
  {
    CandidateID = item.Object.CandidateID,
    ApplicationDate = item.Object.ApplicationDate,
    ApplicationTime = item.Object.ApplicationTime,
    CandidateName = canInfo.Find(a => a.CandidateId == item.Object.CandidateID).Name + " " + canInfo.Find(a => a.CandidateId == item.Object.CandidateID).LastName,
    NewCanID = item.Object.CandidateID.Substring(1),
    ImageURL = GetFile(item.Object.CandidateID.Substring(1) + "-One.jpg") // error
  }).ToList();
}

您需要在从GetFile 返回的Task&lt;string&gt; 上使用await,这要求传递给Select 的lambda 为async

public async Task<List<JobApplication>> GetApplications()
{
  var canInfo = await GetCandidates();
  var jobApplication = await GlobalVar.firebaseClient
          .Child("JobApplication")
          .OnceAsync<JobApplication>();
  return jobApplication.Select(async item => new JobApplication
  {
    CandidateID = item.Object.CandidateID,
    ApplicationDate = item.Object.ApplicationDate,
    ApplicationTime = item.Object.ApplicationTime,
    CandidateName = canInfo.Find(a => a.CandidateId == item.Object.CandidateID).Name + " " + canInfo.Find(a => a.CandidateId == item.Object.CandidateID).LastName,
    NewCanID = item.Object.CandidateID.Substring(1),
    ImageURL = await GetFile(item.Object.CandidateID.Substring(1) + "-One.jpg")
  }).ToList();
  // error: the code is now trying to return Task<List<Task<JobApplication>>>
}

现在,您有一个从Select 返回的任务序列。您可以(异步)等待他们一次完成一个:

public async Task<List<JobApplication>> GetApplications()
{
  var canInfo = await GetCandidates();
  var jobApplication = await GlobalVar.firebaseClient
          .Child("JobApplication")
          .OnceAsync<JobApplication>();
  var result = new List<JobApplication>();
  foreach (var item in jobApplication)
  {
    result.Add(new JobApplication
    {
      CandidateID = item.Object.CandidateID,
      ApplicationDate = item.Object.ApplicationDate,
      ApplicationTime = item.Object.ApplicationTime,
      CandidateName = canInfo.Find(a => a.CandidateId == item.Object.CandidateID).Name + " " + canInfo.Find(a => a.CandidateId == item.Object.CandidateID).LastName,
      NewCanID = item.Object.CandidateID.Substring(1),
      ImageURL = await GetFile(item.Object.CandidateID.Substring(1) + "-One.jpg")
    });
  }
  return result;
}

或者,您可以同时启动它们,然后等待它们全部完成:

public async Task<List<JobApplication>> GetApplications()
{
  var canInfo = await GetCandidates();
  var jobApplication = await GlobalVar.firebaseClient
          .Child("JobApplication")
          .OnceAsync<JobApplication>();
  var tasks = jobApplication.Select(async item => new JobApplication
  {
    CandidateID = item.Object.CandidateID,
    ApplicationDate = item.Object.ApplicationDate,
    ApplicationTime = item.Object.ApplicationTime,
    CandidateName = canInfo.Find(a => a.CandidateId == item.Object.CandidateID).Name + " " + canInfo.Find(a => a.CandidateId == item.Object.CandidateID).LastName,
    NewCanID = item.Object.CandidateID.Substring(1),
    ImageURL = await GetFile(item.Object.CandidateID.Substring(1) + "-One.jpg")
  }).ToList();
  var result = await Task.WhenAll(tasks);
  return result.ToList();
}

【讨论】:

  • 非常感谢您清楚地解释如何解决这个问题。我是 C# 的新手,所以我仍在努力了解很多事情,但这对我有很大帮助。我使用了您的第一个示例,并且能够在“for each”行之后检查该文件是否在线,以防止发生错误。
猜你喜欢
  • 2014-07-19
  • 1970-01-01
  • 2014-02-27
  • 2021-05-01
  • 1970-01-01
  • 2012-07-21
  • 2015-02-26
  • 2012-07-15
  • 1970-01-01
相关资源
最近更新 更多