Using async WhenStarted & WhenStopped methods within TopShelf
up vote
1
down vote
favorite
We use TopShelf like so to start our services. We are seeing slightly odd issues around Service Start and Stop though and wondered if it was due to our async start / stop methods. Having looked at the documentation using async is never mentioned. There is one mentionon their github pages which states that you should not use async in this manner.
But, having said that, it compiles and runs (mostly) ok. So is this correct or should I use a .Wait()
instead?
var host = HostFactory.New(hostConfig =>
{
hostConfig.Service<StreamClient>(serviceConfig =>
{
serviceConfig.ConstructUsing(name => new StreamClient());
serviceConfig.WhenStarted(async tc => await tc.Start());
serviceConfig.WhenStopped(async tc => await tc.Stop());
});
hostConfig.RunAsLocalSystem();
hostConfig.SetDescription("Stream Client Service");
hostConfig.SetDisplayName("Stream Client Service");
hostConfig.SetServiceName("StreamClientService");
});
host.Run();
@Nkosi asked what the method signatures look like, they are async heavy and start internal clients and processes.
public async Task Start()
{
// Dont start again if we are already running, or if we are already in the starting state
if (this.Running || this.Starting)
{
return;
}
await this.slackService.SendSlackServiceEvent(ServiceEventType.Starting, serviceName, applicationVersion);
this.Starting = true;
this.Stopping = false;
var configurationBuilder = new ClientConfigurationBuilder();
ClientConfiguration clientConfiguration;
if (Constants.UseLocalConnection)
{
await this.OnClientDebugMessage($"Using Local Connection");
clientConfiguration = configurationBuilder.CreateLocalConfiguration();
}
else
{
await this.OnClientDebugMessage($"Using SQL Connection");
clientConfiguration = configurationBuilder.CreateSqlConfiguration();
}
this.ClusterGrainClient = await this.StartClient(clientConfiguration);
if (this.ClusterGrainClient == null)
{
using (ConsoleColours.TextColour(ConsoleColor.Red))
{
await this.OnClientDebugMessage($"Cluster client null, aborting!");
}
return;
}
this.Running = true;
await this.OnClientStarted();
await this.slackService.SendSlackServiceEvent(ServiceEventType.Started, serviceName, applicationVersion);
this.Starting = false;
}
c# .net async-await topshelf
|
show 1 more comment
up vote
1
down vote
favorite
We use TopShelf like so to start our services. We are seeing slightly odd issues around Service Start and Stop though and wondered if it was due to our async start / stop methods. Having looked at the documentation using async is never mentioned. There is one mentionon their github pages which states that you should not use async in this manner.
But, having said that, it compiles and runs (mostly) ok. So is this correct or should I use a .Wait()
instead?
var host = HostFactory.New(hostConfig =>
{
hostConfig.Service<StreamClient>(serviceConfig =>
{
serviceConfig.ConstructUsing(name => new StreamClient());
serviceConfig.WhenStarted(async tc => await tc.Start());
serviceConfig.WhenStopped(async tc => await tc.Stop());
});
hostConfig.RunAsLocalSystem();
hostConfig.SetDescription("Stream Client Service");
hostConfig.SetDisplayName("Stream Client Service");
hostConfig.SetServiceName("StreamClientService");
});
host.Run();
@Nkosi asked what the method signatures look like, they are async heavy and start internal clients and processes.
public async Task Start()
{
// Dont start again if we are already running, or if we are already in the starting state
if (this.Running || this.Starting)
{
return;
}
await this.slackService.SendSlackServiceEvent(ServiceEventType.Starting, serviceName, applicationVersion);
this.Starting = true;
this.Stopping = false;
var configurationBuilder = new ClientConfigurationBuilder();
ClientConfiguration clientConfiguration;
if (Constants.UseLocalConnection)
{
await this.OnClientDebugMessage($"Using Local Connection");
clientConfiguration = configurationBuilder.CreateLocalConfiguration();
}
else
{
await this.OnClientDebugMessage($"Using SQL Connection");
clientConfiguration = configurationBuilder.CreateSqlConfiguration();
}
this.ClusterGrainClient = await this.StartClient(clientConfiguration);
if (this.ClusterGrainClient == null)
{
using (ConsoleColours.TextColour(ConsoleColor.Red))
{
await this.OnClientDebugMessage($"Cluster client null, aborting!");
}
return;
}
this.Running = true;
await this.OnClientStarted();
await this.slackService.SendSlackServiceEvent(ServiceEventType.Started, serviceName, applicationVersion);
this.Starting = false;
}
c# .net async-await topshelf
What do the method signatures look like for when started and when stopped?
– Nkosi
Nov 8 at 10:18
@Nkosi Fair point - Updated the question
– Chris
Nov 8 at 10:22
1
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
– Nkosi
Nov 8 at 10:22
@Nkosi Could you post some sample code please? How can I await an async method within a synchronous method without using.Wait()
? In which case why can't I wait within the TopShelfWhenStarted
method? THanks
– Chris
Nov 8 at 10:24
Because you are essentially doing anasync void
in those delegates which are fire and forget. Event handlers are the one exception to that rule where it is allowed
– Nkosi
Nov 8 at 10:26
|
show 1 more comment
up vote
1
down vote
favorite
up vote
1
down vote
favorite
We use TopShelf like so to start our services. We are seeing slightly odd issues around Service Start and Stop though and wondered if it was due to our async start / stop methods. Having looked at the documentation using async is never mentioned. There is one mentionon their github pages which states that you should not use async in this manner.
But, having said that, it compiles and runs (mostly) ok. So is this correct or should I use a .Wait()
instead?
var host = HostFactory.New(hostConfig =>
{
hostConfig.Service<StreamClient>(serviceConfig =>
{
serviceConfig.ConstructUsing(name => new StreamClient());
serviceConfig.WhenStarted(async tc => await tc.Start());
serviceConfig.WhenStopped(async tc => await tc.Stop());
});
hostConfig.RunAsLocalSystem();
hostConfig.SetDescription("Stream Client Service");
hostConfig.SetDisplayName("Stream Client Service");
hostConfig.SetServiceName("StreamClientService");
});
host.Run();
@Nkosi asked what the method signatures look like, they are async heavy and start internal clients and processes.
public async Task Start()
{
// Dont start again if we are already running, or if we are already in the starting state
if (this.Running || this.Starting)
{
return;
}
await this.slackService.SendSlackServiceEvent(ServiceEventType.Starting, serviceName, applicationVersion);
this.Starting = true;
this.Stopping = false;
var configurationBuilder = new ClientConfigurationBuilder();
ClientConfiguration clientConfiguration;
if (Constants.UseLocalConnection)
{
await this.OnClientDebugMessage($"Using Local Connection");
clientConfiguration = configurationBuilder.CreateLocalConfiguration();
}
else
{
await this.OnClientDebugMessage($"Using SQL Connection");
clientConfiguration = configurationBuilder.CreateSqlConfiguration();
}
this.ClusterGrainClient = await this.StartClient(clientConfiguration);
if (this.ClusterGrainClient == null)
{
using (ConsoleColours.TextColour(ConsoleColor.Red))
{
await this.OnClientDebugMessage($"Cluster client null, aborting!");
}
return;
}
this.Running = true;
await this.OnClientStarted();
await this.slackService.SendSlackServiceEvent(ServiceEventType.Started, serviceName, applicationVersion);
this.Starting = false;
}
c# .net async-await topshelf
We use TopShelf like so to start our services. We are seeing slightly odd issues around Service Start and Stop though and wondered if it was due to our async start / stop methods. Having looked at the documentation using async is never mentioned. There is one mentionon their github pages which states that you should not use async in this manner.
But, having said that, it compiles and runs (mostly) ok. So is this correct or should I use a .Wait()
instead?
var host = HostFactory.New(hostConfig =>
{
hostConfig.Service<StreamClient>(serviceConfig =>
{
serviceConfig.ConstructUsing(name => new StreamClient());
serviceConfig.WhenStarted(async tc => await tc.Start());
serviceConfig.WhenStopped(async tc => await tc.Stop());
});
hostConfig.RunAsLocalSystem();
hostConfig.SetDescription("Stream Client Service");
hostConfig.SetDisplayName("Stream Client Service");
hostConfig.SetServiceName("StreamClientService");
});
host.Run();
@Nkosi asked what the method signatures look like, they are async heavy and start internal clients and processes.
public async Task Start()
{
// Dont start again if we are already running, or if we are already in the starting state
if (this.Running || this.Starting)
{
return;
}
await this.slackService.SendSlackServiceEvent(ServiceEventType.Starting, serviceName, applicationVersion);
this.Starting = true;
this.Stopping = false;
var configurationBuilder = new ClientConfigurationBuilder();
ClientConfiguration clientConfiguration;
if (Constants.UseLocalConnection)
{
await this.OnClientDebugMessage($"Using Local Connection");
clientConfiguration = configurationBuilder.CreateLocalConfiguration();
}
else
{
await this.OnClientDebugMessage($"Using SQL Connection");
clientConfiguration = configurationBuilder.CreateSqlConfiguration();
}
this.ClusterGrainClient = await this.StartClient(clientConfiguration);
if (this.ClusterGrainClient == null)
{
using (ConsoleColours.TextColour(ConsoleColor.Red))
{
await this.OnClientDebugMessage($"Cluster client null, aborting!");
}
return;
}
this.Running = true;
await this.OnClientStarted();
await this.slackService.SendSlackServiceEvent(ServiceEventType.Started, serviceName, applicationVersion);
this.Starting = false;
}
c# .net async-await topshelf
c# .net async-await topshelf
edited Nov 8 at 10:22
asked Nov 8 at 10:03
Chris
14.2k38149270
14.2k38149270
What do the method signatures look like for when started and when stopped?
– Nkosi
Nov 8 at 10:18
@Nkosi Fair point - Updated the question
– Chris
Nov 8 at 10:22
1
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
– Nkosi
Nov 8 at 10:22
@Nkosi Could you post some sample code please? How can I await an async method within a synchronous method without using.Wait()
? In which case why can't I wait within the TopShelfWhenStarted
method? THanks
– Chris
Nov 8 at 10:24
Because you are essentially doing anasync void
in those delegates which are fire and forget. Event handlers are the one exception to that rule where it is allowed
– Nkosi
Nov 8 at 10:26
|
show 1 more comment
What do the method signatures look like for when started and when stopped?
– Nkosi
Nov 8 at 10:18
@Nkosi Fair point - Updated the question
– Chris
Nov 8 at 10:22
1
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
– Nkosi
Nov 8 at 10:22
@Nkosi Could you post some sample code please? How can I await an async method within a synchronous method without using.Wait()
? In which case why can't I wait within the TopShelfWhenStarted
method? THanks
– Chris
Nov 8 at 10:24
Because you are essentially doing anasync void
in those delegates which are fire and forget. Event handlers are the one exception to that rule where it is allowed
– Nkosi
Nov 8 at 10:26
What do the method signatures look like for when started and when stopped?
– Nkosi
Nov 8 at 10:18
What do the method signatures look like for when started and when stopped?
– Nkosi
Nov 8 at 10:18
@Nkosi Fair point - Updated the question
– Chris
Nov 8 at 10:22
@Nkosi Fair point - Updated the question
– Chris
Nov 8 at 10:22
1
1
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
– Nkosi
Nov 8 at 10:22
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
– Nkosi
Nov 8 at 10:22
@Nkosi Could you post some sample code please? How can I await an async method within a synchronous method without using
.Wait()
? In which case why can't I wait within the TopShelf WhenStarted
method? THanks– Chris
Nov 8 at 10:24
@Nkosi Could you post some sample code please? How can I await an async method within a synchronous method without using
.Wait()
? In which case why can't I wait within the TopShelf WhenStarted
method? THanks– Chris
Nov 8 at 10:24
Because you are essentially doing an
async void
in those delegates which are fire and forget. Event handlers are the one exception to that rule where it is allowed– Nkosi
Nov 8 at 10:26
Because you are essentially doing an
async void
in those delegates which are fire and forget. Event handlers are the one exception to that rule where it is allowed– Nkosi
Nov 8 at 10:26
|
show 1 more comment
2 Answers
2
active
oldest
votes
up vote
1
down vote
accepted
You are essentially doing an async void
in those delegates which are fire and forget.
Reference Async/Await - Best Practices in Asynchronous Programming
Event handlers are the one exception to that rule where it is allowed
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
public void Start() {
Started += OnStarted; //subscribe to event
Started(this, EventArgs.Empty); //raise event
}
private event EventHandler Started = delegate { };
private async void OnStart(object sender, EventArgs args) {
Started -= OnStarted;
await StartAsync();
}
public async Task StartAsync() {
// ...
}
And then call the start as normal
serviceConfig.WhenStarted(_ => _.Start());
which would raise the event and flow as expected.
Thank you, may I ask how this is better than simply putting a.Wait()
on my existing asyncStart()
method? Similar to what Paulo posted?
– Chris
Nov 8 at 10:55
1
That runs the greater risk of causing deadlocks. Refer to the linked article in the answer.
– Nkosi
Nov 8 at 10:56
The article actually states that console applications are not affected by deadlock and an example is given using .Wait()
– Migg
Nov 9 at 2:00
add a comment |
up vote
2
down vote
Regardless of being Topshelf or not, the Windows Service host will start the service, not run it.
I've never tried it my self, but you might try something like this:
public void Start() => this.StartAsync().GetAwaiter().GetResult();
public void Stop() => this.Stop().GetAwaiter().GetResult();
public async Task StartAsync()
{
// ...
}
public async Task StopAsync()
{
// ...
}
This should be the correct answer. Starting your program's service from a console application doesn't really apply. Figure 4 of an article (msdn.microsoft.com/en-us/magazine/jj991977.aspx) by Stephen Cleary does mention this, though he recommends using AsyncEx.Note that console applications don’t cause this deadlock.
...This difference in behavior can be confusing when programmers write a test console program, observe the partially async code work as expected, and then move the same code into a GUI or ASP.NET application, where it deadlocks
– Migg
Nov 9 at 1:54
The difference between.Result
and.Wait()
and.GetAwaiter().GetResult()
is that the latter unwraps the exception if one is thrown.
– Paulo Morgado
Nov 9 at 7:28
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
You are essentially doing an async void
in those delegates which are fire and forget.
Reference Async/Await - Best Practices in Asynchronous Programming
Event handlers are the one exception to that rule where it is allowed
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
public void Start() {
Started += OnStarted; //subscribe to event
Started(this, EventArgs.Empty); //raise event
}
private event EventHandler Started = delegate { };
private async void OnStart(object sender, EventArgs args) {
Started -= OnStarted;
await StartAsync();
}
public async Task StartAsync() {
// ...
}
And then call the start as normal
serviceConfig.WhenStarted(_ => _.Start());
which would raise the event and flow as expected.
Thank you, may I ask how this is better than simply putting a.Wait()
on my existing asyncStart()
method? Similar to what Paulo posted?
– Chris
Nov 8 at 10:55
1
That runs the greater risk of causing deadlocks. Refer to the linked article in the answer.
– Nkosi
Nov 8 at 10:56
The article actually states that console applications are not affected by deadlock and an example is given using .Wait()
– Migg
Nov 9 at 2:00
add a comment |
up vote
1
down vote
accepted
You are essentially doing an async void
in those delegates which are fire and forget.
Reference Async/Await - Best Practices in Asynchronous Programming
Event handlers are the one exception to that rule where it is allowed
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
public void Start() {
Started += OnStarted; //subscribe to event
Started(this, EventArgs.Empty); //raise event
}
private event EventHandler Started = delegate { };
private async void OnStart(object sender, EventArgs args) {
Started -= OnStarted;
await StartAsync();
}
public async Task StartAsync() {
// ...
}
And then call the start as normal
serviceConfig.WhenStarted(_ => _.Start());
which would raise the event and flow as expected.
Thank you, may I ask how this is better than simply putting a.Wait()
on my existing asyncStart()
method? Similar to what Paulo posted?
– Chris
Nov 8 at 10:55
1
That runs the greater risk of causing deadlocks. Refer to the linked article in the answer.
– Nkosi
Nov 8 at 10:56
The article actually states that console applications are not affected by deadlock and an example is given using .Wait()
– Migg
Nov 9 at 2:00
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
You are essentially doing an async void
in those delegates which are fire and forget.
Reference Async/Await - Best Practices in Asynchronous Programming
Event handlers are the one exception to that rule where it is allowed
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
public void Start() {
Started += OnStarted; //subscribe to event
Started(this, EventArgs.Empty); //raise event
}
private event EventHandler Started = delegate { };
private async void OnStart(object sender, EventArgs args) {
Started -= OnStarted;
await StartAsync();
}
public async Task StartAsync() {
// ...
}
And then call the start as normal
serviceConfig.WhenStarted(_ => _.Start());
which would raise the event and flow as expected.
You are essentially doing an async void
in those delegates which are fire and forget.
Reference Async/Await - Best Practices in Asynchronous Programming
Event handlers are the one exception to that rule where it is allowed
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
public void Start() {
Started += OnStarted; //subscribe to event
Started(this, EventArgs.Empty); //raise event
}
private event EventHandler Started = delegate { };
private async void OnStart(object sender, EventArgs args) {
Started -= OnStarted;
await StartAsync();
}
public async Task StartAsync() {
// ...
}
And then call the start as normal
serviceConfig.WhenStarted(_ => _.Start());
which would raise the event and flow as expected.
answered Nov 8 at 10:40
Nkosi
103k14107175
103k14107175
Thank you, may I ask how this is better than simply putting a.Wait()
on my existing asyncStart()
method? Similar to what Paulo posted?
– Chris
Nov 8 at 10:55
1
That runs the greater risk of causing deadlocks. Refer to the linked article in the answer.
– Nkosi
Nov 8 at 10:56
The article actually states that console applications are not affected by deadlock and an example is given using .Wait()
– Migg
Nov 9 at 2:00
add a comment |
Thank you, may I ask how this is better than simply putting a.Wait()
on my existing asyncStart()
method? Similar to what Paulo posted?
– Chris
Nov 8 at 10:55
1
That runs the greater risk of causing deadlocks. Refer to the linked article in the answer.
– Nkosi
Nov 8 at 10:56
The article actually states that console applications are not affected by deadlock and an example is given using .Wait()
– Migg
Nov 9 at 2:00
Thank you, may I ask how this is better than simply putting a
.Wait()
on my existing async Start()
method? Similar to what Paulo posted?– Chris
Nov 8 at 10:55
Thank you, may I ask how this is better than simply putting a
.Wait()
on my existing async Start()
method? Similar to what Paulo posted?– Chris
Nov 8 at 10:55
1
1
That runs the greater risk of causing deadlocks. Refer to the linked article in the answer.
– Nkosi
Nov 8 at 10:56
That runs the greater risk of causing deadlocks. Refer to the linked article in the answer.
– Nkosi
Nov 8 at 10:56
The article actually states that console applications are not affected by deadlock and an example is given using .Wait()
– Migg
Nov 9 at 2:00
The article actually states that console applications are not affected by deadlock and an example is given using .Wait()
– Migg
Nov 9 at 2:00
add a comment |
up vote
2
down vote
Regardless of being Topshelf or not, the Windows Service host will start the service, not run it.
I've never tried it my self, but you might try something like this:
public void Start() => this.StartAsync().GetAwaiter().GetResult();
public void Stop() => this.Stop().GetAwaiter().GetResult();
public async Task StartAsync()
{
// ...
}
public async Task StopAsync()
{
// ...
}
This should be the correct answer. Starting your program's service from a console application doesn't really apply. Figure 4 of an article (msdn.microsoft.com/en-us/magazine/jj991977.aspx) by Stephen Cleary does mention this, though he recommends using AsyncEx.Note that console applications don’t cause this deadlock.
...This difference in behavior can be confusing when programmers write a test console program, observe the partially async code work as expected, and then move the same code into a GUI or ASP.NET application, where it deadlocks
– Migg
Nov 9 at 1:54
The difference between.Result
and.Wait()
and.GetAwaiter().GetResult()
is that the latter unwraps the exception if one is thrown.
– Paulo Morgado
Nov 9 at 7:28
add a comment |
up vote
2
down vote
Regardless of being Topshelf or not, the Windows Service host will start the service, not run it.
I've never tried it my self, but you might try something like this:
public void Start() => this.StartAsync().GetAwaiter().GetResult();
public void Stop() => this.Stop().GetAwaiter().GetResult();
public async Task StartAsync()
{
// ...
}
public async Task StopAsync()
{
// ...
}
This should be the correct answer. Starting your program's service from a console application doesn't really apply. Figure 4 of an article (msdn.microsoft.com/en-us/magazine/jj991977.aspx) by Stephen Cleary does mention this, though he recommends using AsyncEx.Note that console applications don’t cause this deadlock.
...This difference in behavior can be confusing when programmers write a test console program, observe the partially async code work as expected, and then move the same code into a GUI or ASP.NET application, where it deadlocks
– Migg
Nov 9 at 1:54
The difference between.Result
and.Wait()
and.GetAwaiter().GetResult()
is that the latter unwraps the exception if one is thrown.
– Paulo Morgado
Nov 9 at 7:28
add a comment |
up vote
2
down vote
up vote
2
down vote
Regardless of being Topshelf or not, the Windows Service host will start the service, not run it.
I've never tried it my self, but you might try something like this:
public void Start() => this.StartAsync().GetAwaiter().GetResult();
public void Stop() => this.Stop().GetAwaiter().GetResult();
public async Task StartAsync()
{
// ...
}
public async Task StopAsync()
{
// ...
}
Regardless of being Topshelf or not, the Windows Service host will start the service, not run it.
I've never tried it my self, but you might try something like this:
public void Start() => this.StartAsync().GetAwaiter().GetResult();
public void Stop() => this.Stop().GetAwaiter().GetResult();
public async Task StartAsync()
{
// ...
}
public async Task StopAsync()
{
// ...
}
answered Nov 8 at 10:31
Paulo Morgado
5,24711531
5,24711531
This should be the correct answer. Starting your program's service from a console application doesn't really apply. Figure 4 of an article (msdn.microsoft.com/en-us/magazine/jj991977.aspx) by Stephen Cleary does mention this, though he recommends using AsyncEx.Note that console applications don’t cause this deadlock.
...This difference in behavior can be confusing when programmers write a test console program, observe the partially async code work as expected, and then move the same code into a GUI or ASP.NET application, where it deadlocks
– Migg
Nov 9 at 1:54
The difference between.Result
and.Wait()
and.GetAwaiter().GetResult()
is that the latter unwraps the exception if one is thrown.
– Paulo Morgado
Nov 9 at 7:28
add a comment |
This should be the correct answer. Starting your program's service from a console application doesn't really apply. Figure 4 of an article (msdn.microsoft.com/en-us/magazine/jj991977.aspx) by Stephen Cleary does mention this, though he recommends using AsyncEx.Note that console applications don’t cause this deadlock.
...This difference in behavior can be confusing when programmers write a test console program, observe the partially async code work as expected, and then move the same code into a GUI or ASP.NET application, where it deadlocks
– Migg
Nov 9 at 1:54
The difference between.Result
and.Wait()
and.GetAwaiter().GetResult()
is that the latter unwraps the exception if one is thrown.
– Paulo Morgado
Nov 9 at 7:28
This should be the correct answer. Starting your program's service from a console application doesn't really apply. Figure 4 of an article (msdn.microsoft.com/en-us/magazine/jj991977.aspx) by Stephen Cleary does mention this, though he recommends using AsyncEx.
Note that console applications don’t cause this deadlock.
... This difference in behavior can be confusing when programmers write a test console program, observe the partially async code work as expected, and then move the same code into a GUI or ASP.NET application, where it deadlocks
– Migg
Nov 9 at 1:54
This should be the correct answer. Starting your program's service from a console application doesn't really apply. Figure 4 of an article (msdn.microsoft.com/en-us/magazine/jj991977.aspx) by Stephen Cleary does mention this, though he recommends using AsyncEx.
Note that console applications don’t cause this deadlock.
... This difference in behavior can be confusing when programmers write a test console program, observe the partially async code work as expected, and then move the same code into a GUI or ASP.NET application, where it deadlocks
– Migg
Nov 9 at 1:54
The difference between
.Result
and .Wait()
and .GetAwaiter().GetResult()
is that the latter unwraps the exception if one is thrown.– Paulo Morgado
Nov 9 at 7:28
The difference between
.Result
and .Wait()
and .GetAwaiter().GetResult()
is that the latter unwraps the exception if one is thrown.– Paulo Morgado
Nov 9 at 7:28
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53205410%2fusing-async-whenstarted-whenstopped-methods-within-topshelf%23new-answer', 'question_page');
}
);
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
What do the method signatures look like for when started and when stopped?
– Nkosi
Nov 8 at 10:18
@Nkosi Fair point - Updated the question
– Chris
Nov 8 at 10:22
1
Convert your start and stop methods to synchronous methods that raise async events that can be awaited internally.
– Nkosi
Nov 8 at 10:22
@Nkosi Could you post some sample code please? How can I await an async method within a synchronous method without using
.Wait()
? In which case why can't I wait within the TopShelfWhenStarted
method? THanks– Chris
Nov 8 at 10:24
Because you are essentially doing an
async void
in those delegates which are fire and forget. Event handlers are the one exception to that rule where it is allowed– Nkosi
Nov 8 at 10:26