无法将类型“string”隐式转换为“System.Threading.Tasks.Task<string>”
Posted
技术标签:
【中文标题】无法将类型“string”隐式转换为“System.Threading.Tasks.Task<string>”【英文标题】:Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>' 【发布时间】:2013-01-17 10:56:53 【问题描述】:我是异步编程的新手,所以在看了一些异步示例代码之后,我想到了写一个简单的异步代码
我创建了一个简单的 Winform 应用程序,并在表单中编写了以下代码。但它只是不工作
private Task<string> methodAsync()
Thread.Sleep(10000);
return "Hello"; //Error: Cannot implicitly convert type 'string' to 'System.Threading.Tasks.Task<string>'
private async void button1_Click(object sender, EventArgs e)
string s = await methodAsync();
MessageBox.Show(s);
有人可以在这里放点灯吗..
【问题讨论】:
【参考方案1】:列出的方法返回类型是Task<string>
。您正在尝试返回 string
。它们不一样,也没有从字符串到Task<string>
的隐式转换,因此出现错误。
您可能会将此与async
方法混淆,其中返回值由编译器自动包装在Task
中。目前该方法不是异步方法。你几乎肯定是打算这样做的:
private async Task<string> methodAsync()
await Task.Delay(10000);
return "Hello";
有两个关键变化。首先,方法被标记为async
,这意味着返回类型被包裹在Task
中,使得方法可以编译。接下来,我们不想进行阻塞等待。作为一般规则,在使用await
模型时,尽可能避免阻塞等待。 Task.Delay
是一个将在指定的毫秒数后完成的任务。通过await
-ing 该任务,我们有效地执行了该时间的非阻塞等待(实际上该方法的其余部分是该任务的延续)。
如果您更喜欢 4.0 的方式,而不使用 await
,您可以这样做:
private Task<string> methodAsync()
return Task.Delay(10000)
.ContinueWith(t => "Hello");
第一个版本将编译成或多或少像这样的东西,但它会包含一些额外的样板代码,用于支持错误处理和 await
的其他功能,我们在这里没有利用。
如果您的Thread.Sleep(10000)
真的只是作为某个长时间运行方法的占位符,而不是等待一段时间,那么您需要确保工作在另一个线程中完成,而不是当前的上下文。最简单的方法是通过Task.Run
:
private Task<string> methodAsync()
return Task.Run(()=>
SomeLongRunningMethod();
return "Hello";
);
或者更有可能:
private Task<string> methodAsync()
return Task.Run(()=>
return SomeLongRunningMethodThatReturnsAString();
);
【讨论】:
我怎样才能将string
明确地包装在Task
中?或者在被调用的方法中不使用async
和await
(在这种情况下为methodAsync)有没有办法返回Task
或Task<T>
?
@Aniket 不,你错了,有很多方法可以在任务中显式包装字符串。我将在其中编辑解决方案。
@Servy:假设我没有使用延迟和其他代码,这导致methodAsync
中的延迟相同,我应该如何通过将结果字符串包装在任务中来返回结果字符串?
您可以使用 Task.FromResult 将字符串包装在 Task 中。
@dotNETbeginner 好吧,如果您不相信我,您可以自己尝试一下。 await
的意思是,启动该任务,一旦启动,就为该任务添加一个延续,并在异步任务完成后继续使用我停止的方法。如果你只是在异步方法中使用Sleep
然后Task.FromResult
它将花费整个 10 秒来启动任务,在它完成之前永远不会返回给调用者,从而一直阻塞 UI 线程并有效地运行整个事情同步进行。【参考方案2】:
使用 FromResult 方法
public async Task<string> GetString()
System.Threading.Thread.Sleep(5000);
return await Task.FromResult("Hello");
【讨论】:
谢谢,这正是我所需要的,没有提供其他答案。 据我所知,这个答案是实现使用同步实现的 Task除了@Servy 指出的async
的问题使用之外,另一个问题是您需要通过调用Task.Result 从Task<T>
显式获取T
。请注意,Result 属性将阻止异步代码,应谨慎使用。
试试:
private async void button1_Click(object sender, EventArgs e)
var s = await methodAsync();
MessageBox.Show(s.Result);
【讨论】:
虽然这可能不被强烈推荐,但有一个实例我想在catch
中取回Task<string>
内容。我不能await
和.ToString()
产生不正确的结果。这符合要求。【参考方案4】:
//source
public async Task<string> methodName()
return Data;
//Consumption
methodName().Result;
希望这会有所帮助:)
【讨论】:
【参考方案5】:就我而言。
string ip = _GetStoreIpaddress().Result;
private async Task<string> _GetStoreIpaddress()
string _store_iP = "";
var Ip_address = await App.SQLiteDb.GetItemsAsync();
if (Ip_address != null)
_store_iP = Ip_address.ToString();
return _store_iP;
【讨论】:
首先,这并不能回答所提出的问题。其次,这段代码确实有很多问题。非常奇怪的符号,在这个微小的方法中甚至不一致。将 Result() 调用显示为解决方案的一部分是另一个大问题。以上是关于无法将类型“string”隐式转换为“System.Threading.Tasks.Task<string>”的主要内容,如果未能解决你的问题,请参考以下文章
无法将类型“System.DateTime”隐式转换为“string”
无法将类型“string”隐式转换为“System.Threading.Tasks.Task<string>”
无法将类型“字符串”隐式转换为“System.Data.SqlClient.Sqlconnection”
asp.net 无法将类型“System.DateTime”隐式转换为“string”