Use of Async/Await for EventHandlers
I have a MVC WinForms application. I am using Dependency Injection with Ninject as the IoC container.
public class SqlObjectExplorerController : ToolController, ISqlObjectExplorerController
{
private ISqlObjectExplorerView view = null;
private SqlServerStructureProvider structureProvider;
private IProgress<IProgressInfo> progress;
public SqlObjectExplorerController(ISqlObjectExplorerView view)
{
if (view == null)
throw new ArgumentNullException("view");
this.view = view;
InitializeEventHandlers();
...
}
private void InitializeEventHandlers()
{
(view as ToolView).Initialize += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
view.OnRefreshObjectExplorerClicked += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
view.OnAddServerInstanceClicked += new EventHandler(async (s, e) => await AddServerInstanceAsync());
view.OnNewSqlQueryClicked += new EventHandler<NewSqlQueryRequestEventArgs>((s, e) => OpenNewSqlQueryDocument(e));
view.OnExpandRequested += new EventHandler<BeforeExpandEventArgs>((s, e) => BuildSubStructureForDatabaseNode(e));
}
private async Task RefreshObjectExplorerAsync()
{
await InitializeObjectExplorerAsync();
view.InitializeObjectExplorer(ServerCache);
}
... // Lots more code.
My question concerns the use of async/await in setting up the likes of += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
. There are some tasks I need to do on a background thread, so I am using async/await, my questions are about my understanding:
In doing
async (s, e) => await SomeMethodAsync()
I am merely setting up an event handler equivalent toprivate async void SomeMethodAsync(object s, EventArgs e) { ... }
. Which I think is fine in this case of the fire-and-forgetTask
I want to undertake, is it?I don't think there are any problems in setting this up these async handlers in the ctor of the controller, am I right?
The code seems to work fine, but is there something I am not seeing?
c# event-handling winforms async-await
add a comment |
I have a MVC WinForms application. I am using Dependency Injection with Ninject as the IoC container.
public class SqlObjectExplorerController : ToolController, ISqlObjectExplorerController
{
private ISqlObjectExplorerView view = null;
private SqlServerStructureProvider structureProvider;
private IProgress<IProgressInfo> progress;
public SqlObjectExplorerController(ISqlObjectExplorerView view)
{
if (view == null)
throw new ArgumentNullException("view");
this.view = view;
InitializeEventHandlers();
...
}
private void InitializeEventHandlers()
{
(view as ToolView).Initialize += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
view.OnRefreshObjectExplorerClicked += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
view.OnAddServerInstanceClicked += new EventHandler(async (s, e) => await AddServerInstanceAsync());
view.OnNewSqlQueryClicked += new EventHandler<NewSqlQueryRequestEventArgs>((s, e) => OpenNewSqlQueryDocument(e));
view.OnExpandRequested += new EventHandler<BeforeExpandEventArgs>((s, e) => BuildSubStructureForDatabaseNode(e));
}
private async Task RefreshObjectExplorerAsync()
{
await InitializeObjectExplorerAsync();
view.InitializeObjectExplorer(ServerCache);
}
... // Lots more code.
My question concerns the use of async/await in setting up the likes of += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
. There are some tasks I need to do on a background thread, so I am using async/await, my questions are about my understanding:
In doing
async (s, e) => await SomeMethodAsync()
I am merely setting up an event handler equivalent toprivate async void SomeMethodAsync(object s, EventArgs e) { ... }
. Which I think is fine in this case of the fire-and-forgetTask
I want to undertake, is it?I don't think there are any problems in setting this up these async handlers in the ctor of the controller, am I right?
The code seems to work fine, but is there something I am not seeing?
c# event-handling winforms async-await
add a comment |
I have a MVC WinForms application. I am using Dependency Injection with Ninject as the IoC container.
public class SqlObjectExplorerController : ToolController, ISqlObjectExplorerController
{
private ISqlObjectExplorerView view = null;
private SqlServerStructureProvider structureProvider;
private IProgress<IProgressInfo> progress;
public SqlObjectExplorerController(ISqlObjectExplorerView view)
{
if (view == null)
throw new ArgumentNullException("view");
this.view = view;
InitializeEventHandlers();
...
}
private void InitializeEventHandlers()
{
(view as ToolView).Initialize += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
view.OnRefreshObjectExplorerClicked += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
view.OnAddServerInstanceClicked += new EventHandler(async (s, e) => await AddServerInstanceAsync());
view.OnNewSqlQueryClicked += new EventHandler<NewSqlQueryRequestEventArgs>((s, e) => OpenNewSqlQueryDocument(e));
view.OnExpandRequested += new EventHandler<BeforeExpandEventArgs>((s, e) => BuildSubStructureForDatabaseNode(e));
}
private async Task RefreshObjectExplorerAsync()
{
await InitializeObjectExplorerAsync();
view.InitializeObjectExplorer(ServerCache);
}
... // Lots more code.
My question concerns the use of async/await in setting up the likes of += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
. There are some tasks I need to do on a background thread, so I am using async/await, my questions are about my understanding:
In doing
async (s, e) => await SomeMethodAsync()
I am merely setting up an event handler equivalent toprivate async void SomeMethodAsync(object s, EventArgs e) { ... }
. Which I think is fine in this case of the fire-and-forgetTask
I want to undertake, is it?I don't think there are any problems in setting this up these async handlers in the ctor of the controller, am I right?
The code seems to work fine, but is there something I am not seeing?
c# event-handling winforms async-await
I have a MVC WinForms application. I am using Dependency Injection with Ninject as the IoC container.
public class SqlObjectExplorerController : ToolController, ISqlObjectExplorerController
{
private ISqlObjectExplorerView view = null;
private SqlServerStructureProvider structureProvider;
private IProgress<IProgressInfo> progress;
public SqlObjectExplorerController(ISqlObjectExplorerView view)
{
if (view == null)
throw new ArgumentNullException("view");
this.view = view;
InitializeEventHandlers();
...
}
private void InitializeEventHandlers()
{
(view as ToolView).Initialize += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
view.OnRefreshObjectExplorerClicked += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
view.OnAddServerInstanceClicked += new EventHandler(async (s, e) => await AddServerInstanceAsync());
view.OnNewSqlQueryClicked += new EventHandler<NewSqlQueryRequestEventArgs>((s, e) => OpenNewSqlQueryDocument(e));
view.OnExpandRequested += new EventHandler<BeforeExpandEventArgs>((s, e) => BuildSubStructureForDatabaseNode(e));
}
private async Task RefreshObjectExplorerAsync()
{
await InitializeObjectExplorerAsync();
view.InitializeObjectExplorer(ServerCache);
}
... // Lots more code.
My question concerns the use of async/await in setting up the likes of += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
. There are some tasks I need to do on a background thread, so I am using async/await, my questions are about my understanding:
In doing
async (s, e) => await SomeMethodAsync()
I am merely setting up an event handler equivalent toprivate async void SomeMethodAsync(object s, EventArgs e) { ... }
. Which I think is fine in this case of the fire-and-forgetTask
I want to undertake, is it?I don't think there are any problems in setting this up these async handlers in the ctor of the controller, am I right?
The code seems to work fine, but is there something I am not seeing?
c# event-handling winforms async-await
c# event-handling winforms async-await
asked Jun 30 '16 at 10:18
MoonKnight
3421614
3421614
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
The things to consider when it comes to async
event handlers are:
- Exceptions thrown for the handler might be rethrown on the UI
SynchronizationContext
, which usually crashes the application. - After you raise the event, the handlers won't be completed yet. The execution of a handler might be interleaved with the execution of the code after the raising and execution of multiple handlers can also be interleaved with each other.
Assuming those caveats are acceptable for you, code like this should be fine.
Also:
view.OnRefreshObjectExplorerClicked += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
You should be able to simplify this to just:
view.OnRefreshObjectExplorerClicked += async (s, e) => await RefreshObjectExplorerAsync();
It seems you never unsubscribe the event handlers, are you sure that's okay?
How do you unsubscribe from such an event handler? It's showing the warningEvent unsubscription via anonymous delegate
– Stephan
Sep 27 '18 at 21:01
@Stephan Either you use a regular method instead of a lambda to both subscribe and unsubscribe or you store the delegate that represents the lambda in a variable and use that to subscribe and unsubscribe.
– svick
Sep 27 '18 at 21:47
add a comment |
Here's one more way that worked for me using a method overload:
public void StartWindowsService()
{
var interval = TimeSpan.FromSeconds(2).TotalMilliseconds;
_someTimer = new Timer
{
Interval = interval,
Enabled = true
};
_someTimer.Elapsed += OnTimedEvent;
_someTimer.Start();
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
MyAsyncMethod().Wait();
}
private async Task MyAsyncMethod()
{
// do async stuff here . . .
}
New contributor
so is this code better because it requires fewer lines? if not, please edit and explain how this approach is better
– Sᴀᴍ Onᴇᴌᴀ
1 min ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
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: "196"
};
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',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
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
});
}
});
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f133464%2fuse-of-async-await-for-eventhandlers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
The things to consider when it comes to async
event handlers are:
- Exceptions thrown for the handler might be rethrown on the UI
SynchronizationContext
, which usually crashes the application. - After you raise the event, the handlers won't be completed yet. The execution of a handler might be interleaved with the execution of the code after the raising and execution of multiple handlers can also be interleaved with each other.
Assuming those caveats are acceptable for you, code like this should be fine.
Also:
view.OnRefreshObjectExplorerClicked += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
You should be able to simplify this to just:
view.OnRefreshObjectExplorerClicked += async (s, e) => await RefreshObjectExplorerAsync();
It seems you never unsubscribe the event handlers, are you sure that's okay?
How do you unsubscribe from such an event handler? It's showing the warningEvent unsubscription via anonymous delegate
– Stephan
Sep 27 '18 at 21:01
@Stephan Either you use a regular method instead of a lambda to both subscribe and unsubscribe or you store the delegate that represents the lambda in a variable and use that to subscribe and unsubscribe.
– svick
Sep 27 '18 at 21:47
add a comment |
The things to consider when it comes to async
event handlers are:
- Exceptions thrown for the handler might be rethrown on the UI
SynchronizationContext
, which usually crashes the application. - After you raise the event, the handlers won't be completed yet. The execution of a handler might be interleaved with the execution of the code after the raising and execution of multiple handlers can also be interleaved with each other.
Assuming those caveats are acceptable for you, code like this should be fine.
Also:
view.OnRefreshObjectExplorerClicked += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
You should be able to simplify this to just:
view.OnRefreshObjectExplorerClicked += async (s, e) => await RefreshObjectExplorerAsync();
It seems you never unsubscribe the event handlers, are you sure that's okay?
How do you unsubscribe from such an event handler? It's showing the warningEvent unsubscription via anonymous delegate
– Stephan
Sep 27 '18 at 21:01
@Stephan Either you use a regular method instead of a lambda to both subscribe and unsubscribe or you store the delegate that represents the lambda in a variable and use that to subscribe and unsubscribe.
– svick
Sep 27 '18 at 21:47
add a comment |
The things to consider when it comes to async
event handlers are:
- Exceptions thrown for the handler might be rethrown on the UI
SynchronizationContext
, which usually crashes the application. - After you raise the event, the handlers won't be completed yet. The execution of a handler might be interleaved with the execution of the code after the raising and execution of multiple handlers can also be interleaved with each other.
Assuming those caveats are acceptable for you, code like this should be fine.
Also:
view.OnRefreshObjectExplorerClicked += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
You should be able to simplify this to just:
view.OnRefreshObjectExplorerClicked += async (s, e) => await RefreshObjectExplorerAsync();
It seems you never unsubscribe the event handlers, are you sure that's okay?
The things to consider when it comes to async
event handlers are:
- Exceptions thrown for the handler might be rethrown on the UI
SynchronizationContext
, which usually crashes the application. - After you raise the event, the handlers won't be completed yet. The execution of a handler might be interleaved with the execution of the code after the raising and execution of multiple handlers can also be interleaved with each other.
Assuming those caveats are acceptable for you, code like this should be fine.
Also:
view.OnRefreshObjectExplorerClicked += new EventHandler(async (s, e) => await RefreshObjectExplorerAsync());
You should be able to simplify this to just:
view.OnRefreshObjectExplorerClicked += async (s, e) => await RefreshObjectExplorerAsync();
It seems you never unsubscribe the event handlers, are you sure that's okay?
edited Aug 5 '16 at 12:31
answered Jul 17 '16 at 21:33
svick
22.7k43778
22.7k43778
How do you unsubscribe from such an event handler? It's showing the warningEvent unsubscription via anonymous delegate
– Stephan
Sep 27 '18 at 21:01
@Stephan Either you use a regular method instead of a lambda to both subscribe and unsubscribe or you store the delegate that represents the lambda in a variable and use that to subscribe and unsubscribe.
– svick
Sep 27 '18 at 21:47
add a comment |
How do you unsubscribe from such an event handler? It's showing the warningEvent unsubscription via anonymous delegate
– Stephan
Sep 27 '18 at 21:01
@Stephan Either you use a regular method instead of a lambda to both subscribe and unsubscribe or you store the delegate that represents the lambda in a variable and use that to subscribe and unsubscribe.
– svick
Sep 27 '18 at 21:47
How do you unsubscribe from such an event handler? It's showing the warning
Event unsubscription via anonymous delegate
– Stephan
Sep 27 '18 at 21:01
How do you unsubscribe from such an event handler? It's showing the warning
Event unsubscription via anonymous delegate
– Stephan
Sep 27 '18 at 21:01
@Stephan Either you use a regular method instead of a lambda to both subscribe and unsubscribe or you store the delegate that represents the lambda in a variable and use that to subscribe and unsubscribe.
– svick
Sep 27 '18 at 21:47
@Stephan Either you use a regular method instead of a lambda to both subscribe and unsubscribe or you store the delegate that represents the lambda in a variable and use that to subscribe and unsubscribe.
– svick
Sep 27 '18 at 21:47
add a comment |
Here's one more way that worked for me using a method overload:
public void StartWindowsService()
{
var interval = TimeSpan.FromSeconds(2).TotalMilliseconds;
_someTimer = new Timer
{
Interval = interval,
Enabled = true
};
_someTimer.Elapsed += OnTimedEvent;
_someTimer.Start();
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
MyAsyncMethod().Wait();
}
private async Task MyAsyncMethod()
{
// do async stuff here . . .
}
New contributor
so is this code better because it requires fewer lines? if not, please edit and explain how this approach is better
– Sᴀᴍ Onᴇᴌᴀ
1 min ago
add a comment |
Here's one more way that worked for me using a method overload:
public void StartWindowsService()
{
var interval = TimeSpan.FromSeconds(2).TotalMilliseconds;
_someTimer = new Timer
{
Interval = interval,
Enabled = true
};
_someTimer.Elapsed += OnTimedEvent;
_someTimer.Start();
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
MyAsyncMethod().Wait();
}
private async Task MyAsyncMethod()
{
// do async stuff here . . .
}
New contributor
so is this code better because it requires fewer lines? if not, please edit and explain how this approach is better
– Sᴀᴍ Onᴇᴌᴀ
1 min ago
add a comment |
Here's one more way that worked for me using a method overload:
public void StartWindowsService()
{
var interval = TimeSpan.FromSeconds(2).TotalMilliseconds;
_someTimer = new Timer
{
Interval = interval,
Enabled = true
};
_someTimer.Elapsed += OnTimedEvent;
_someTimer.Start();
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
MyAsyncMethod().Wait();
}
private async Task MyAsyncMethod()
{
// do async stuff here . . .
}
New contributor
Here's one more way that worked for me using a method overload:
public void StartWindowsService()
{
var interval = TimeSpan.FromSeconds(2).TotalMilliseconds;
_someTimer = new Timer
{
Interval = interval,
Enabled = true
};
_someTimer.Elapsed += OnTimedEvent;
_someTimer.Start();
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
MyAsyncMethod().Wait();
}
private async Task MyAsyncMethod()
{
// do async stuff here . . .
}
New contributor
New contributor
answered 24 mins ago
daviesdoesit
1
1
New contributor
New contributor
so is this code better because it requires fewer lines? if not, please edit and explain how this approach is better
– Sᴀᴍ Onᴇᴌᴀ
1 min ago
add a comment |
so is this code better because it requires fewer lines? if not, please edit and explain how this approach is better
– Sᴀᴍ Onᴇᴌᴀ
1 min ago
so is this code better because it requires fewer lines? if not, please edit and explain how this approach is better
– Sᴀᴍ Onᴇᴌᴀ
1 min ago
so is this code better because it requires fewer lines? if not, please edit and explain how this approach is better
– Sᴀᴍ Onᴇᴌᴀ
1 min ago
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
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
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f133464%2fuse-of-async-await-for-eventhandlers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
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
Required, but never shown
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
Required, but never shown
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
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown