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;

}









share|improve this question
























  • 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 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















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;

}









share|improve this question
























  • 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 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













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;

}









share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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


















  • 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 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
















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












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.






share|improve this answer





















  • 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




    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


















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()
{
// ...
}





share|improve this answer





















  • 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











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














 

draft saved


draft discarded


















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
































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.






share|improve this answer





















  • 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




    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















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.






share|improve this answer





















  • 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




    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













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.






share|improve this answer












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.







share|improve this answer












share|improve this answer



share|improve this answer










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 async Start() 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






  • 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












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()
{
// ...
}





share|improve this answer





















  • 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















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()
{
// ...
}





share|improve this answer





















  • 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













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()
{
// ...
}





share|improve this answer












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()
{
// ...
}






share|improve this answer












share|improve this answer



share|improve this answer










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


















  • 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


















 

draft saved


draft discarded



















































 


draft saved


draft discarded














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




















































































Popular posts from this blog

Schultheiß

Verwaltungsgliederung Dänemarks

Liste der Kulturdenkmale in Wilsdruff