2014-06-12 117 views
1

所以我只是想让我的服务层asyncASP NET MVC 5任务异步创建一个异步方法

我有一个新的服务ProjectManagement,我希望它的GetProjects方法是异步的。

public Task<string> GetProjectsAsync() 
{ 
    var json = JsonConvert.SerializeObject(_repository.All<Projects>()); 

    return json; 
} 

我知道这个方法行不通,显然是因为我返回一个字符串,而不是一个Task<string>。那么如何使用Task.Run()来运行此方法并返回结果呢?

我看过这个documentation,我对如何使用它有点困惑?

所有我希望能够在我的控制器做的是:

var jsonData = await _projectManagement.GetProjectsAsync(); 
+2

使方法异步的唯一真正原因是如果你可以异步执行IO。如果你不能,你可以把它作为同步方法。 – Servy

+0

当你有返回类型的方法“任务”时返回一个字符串是正确的行为。只需在你的'GetProjectsAsync()'方法之前放置async即可。 – Abhijeet

+3

@Abhijeet这是一个可怕的想法。这是创建一个同步的方法,只是将其结果包装在一个任务中,实质上是声明它是异步的谎言。你不应该那样做。如果你不想让这个方法异步,你不应该对你的调用者撒谎,并声称你是异步的。 – Servy

回答

5

当转换为async,你要开始“并且朝着你的控制器/ UI工作。我做了很多转换,这是我找到的最好的方法。

因此,首先确定任何自然异步的操作;任何I/O约束是一个很好的选择。你已经确定了一个:数据库调用。

接下来,从最底层代码开始,并使其成为异步。这是你的问题进入的地方;你正在考虑通过使用Task.Run在中间强制异步,但是你需要深入到更低的层次,并使其始终保持异步。

例如,我会假设你的资料库是使用实体框架和你All<T>方法看起来是这样的:

public List<T> All<T>() 
{ 
    return _context.Set<T>().ToList(); 
} 

然后你就开始做这个仓库方法的异步版本:

public Task<List<T>> AllAsync<T>() 
{ 
    return _context.Set<T>().ToListAsync(); 
} 

一旦你有了到位的至少一个异步存储库的方法,你就可以开始改变你的服务层是异步的,所以这段代码:

public string GetProjects() 
{ 
    var json = JsonConvert.SerializeObject(_repository.All<Projects>()); 
    return json; 
} 

变成这样:

public async Task<string> GetProjectsAsync() 
{ 
    var json = JsonConvert.SerializeObject(await _repository.AllAsync<Projects>()); 
    return json; 
} 

一旦服务层是异步的,那么你就可以改变你的控制器是异步的。

+0

我不能实现'AllAsync'方法,因为它说“不能隐式地将列表转换为任务” –

+0

再看看代码。它是'ToListAsync',而不是'ToList'。 –

+0

是的,我做到了:) –

-3

你应该尝试在“叶此链接http://www.dotnetperls.com/async

private async void DoAsyncWork() 
{ 
    var data = await GetProjectAsync(); 
} 

async Task<string> GetProjectAsynce() 
{ 
    // code to get stuff done 
    // await key word may be needed depending on 
    // what you are doinf 
    return JsonConvert.SerializeObject(myRepository.All<Projects>()); 
    // convert to string first of course 
}