[英]How to call some async code in an ASP.NET application_start
In our application_startup, we seed up our database with some fake data, if no data exists. 在我们的application_startup中,如果不存在数据,我们会使用一些假数据为我们的数据库设定数据。
To do this, we're using the Async
methods to store the data. 为此,我们使用
Async
方法来存储数据。 Great. 大。 Only problem is, we're not sure how to do this in the
application_startup
because that's not an async method. 唯一的问题是,我们不确定如何在
application_startup
执行此操作,因为这不是异步方法。
I've spent soooo much time trying to understand @StevenCleary's tutorials and I'm always getting deadlocks. 我花了太多时间试图理解@ StevenCleary的教程,而且我总是遇到死锁。 I totally grok what he consistently says :
我完全理解他一贯说的话 :
As a general rule, you should use "async all the way down";
作为一般规则,你应该使用“async all down down”; that is, don't block on async code
也就是说,不要阻止异步代码
but I just don't get how I can do that, in this case :( 但我只是不知道我怎么能这样做,在这种情况下:(
Lets imagine this is the code I'm trying to play with... 让我们想象这是我正在尝试使用的代码......
protected void Application_Start()
{
var someFakeData = LoadSomeFakeData();
var documentStore = new DocumentStore();
await documentStore.InitializeAsync(someFakeData);
...
// Registers this database as a singleton.
Container.Register(documentStore);
}
and later on .. some code that uses this documentStore
. 以及稍后..使用此
documentStore
一些代码。 It is injected via construction injection ... 它是通过施工注入注入的......
public SomeController(IDocumentStore documentStore)
{
_documentStore = documentStore;
}
public ViewModel GetFoos()
{
using (var session = _documentStore.OpenSession())
{
... db code goes in here ...
}
}
I'm not trying to do some async code in here. 我不是想在这里做一些异步代码。 I'm actually trying to call this async method, synchronously .
我实际上试图同步调用这个异步方法。 Sure, i loose the benefits of async blah blah de blah.. but i'm happy with that.
当然,我放弃了async blah blah de blah的好处......但我很高兴。 This is start up and I'm happy to block on startup.
这是启动,我很高兴在启动时阻止。
In this case, you're asynchronously initializing a shared resource. 在这种情况下,您将异步初始化共享资源。 So, I recommend that you either save the
Task
itself, or introduce an asynchronous wrapper type. 因此,我建议您保存
Task
本身,或者引入异步包装器类型。
Using Task
: 使用
Task
:
protected void Application_Start()
{
var someFakeData = LoadSomeFakeData();
var documentStore = new DocumentStore();
var documentStoreTask = documentStore.InitializeAsync(someFakeData);
...
// Registers this database task as a singleton.
Container.Register(documentStoreTask);
}
That may be too awkward, though, depending on Container
. 但这可能太尴尬了,取决于
Container
。 In that case, you can introduce an asynchronous wrapper type: 在这种情况下,您可以引入异步包装类型:
public sealed class DocumentStoreWrapper
{
private readonly Task<DocumentStore> _documentStore;
public DocumentStoreWrapper(Data data)
{
_documentStore = CreateDocumentStoreAsync(data);
}
private static async Task<DocumentStore> CreateDocumentStoreAsync(Data data)
{
var result = new DocumentStore();
await documentStore.InitializeAsync(data);
...
return result;
}
public Task<DocumentStore> DocumentStoreTask { get { return _documentStore; } }
}
protected void Application_Start()
{
var someFakeData = LoadSomeFakeData();
var documentStoreWrapper = new DocumentStoreWrapper(someFakeData);
...
// Registers this database wrapper as a singleton.
Container.Register(documentStoreWrapper);
}
Or, you could use AsyncLazy<T>
, which does much the same thing but uses a background thread to execute the initialization code. 或者,你可以使用
AsyncLazy<T>
,它做了很多相同的事情,但使用后台线程来执行初始化代码。
You can use of Task.Run(() => YourAsyncMethod());
您可以使用
Task.Run(() => YourAsyncMethod());
inside of none async method like: 在没有异步方法的内部,如:
protected void Application_Start()
{
Task.Run(() => MyAsyncMethod(true));
}
By convention xxxAsync methods should return Task
and from here you can call 按照惯例,xxxAsync方法应该返回
Task
,你可以从这里调用
task.RunSynchronously()
https://msdn.microsoft.com/en-us/library/dd321435%28v=vs.110%29.aspx https://msdn.microsoft.com/en-us/library/dd321435%28v=vs.110%29.aspx
public static class AsyncHelper
{
private static readonly TaskFactory MyTaskFactory = new
TaskFactory(CancellationToken.None,
TaskCreationOptions.None,
TaskContinuationOptions.None,
TaskScheduler.Default);
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
return MyTaskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
public static void RunSync(Func<Task> func)
{
MyTaskFactory
.StartNew(func)
.Unwrap()
.GetAwaiter()
.GetResult();
}
}
then use as 然后用作
AsyncHelper.RunSync(ProcessAsync);
private async Task ProcessAsync(){ ....
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.