Wpf Dispatcher.BeginInvoke delegate issue - wpf

In my WP SignalR application I'm using this code:
_dataHub.Subscribe("ReceiveMessage").Received += list => App.RootFrame.Dispatcher.BeginInvoke(() => Messages.Add(list[0].ToString()));
But I have to use similar code to subscribe to my SignalR server application.
I tried this one:
_dataHub.Subscribe("ReceiveMessage").Received += list => Dispatcher.CurrentDispatcher.BeginInvoke(() => Messages.Add(list[0].ToString()));
I'm having delegate issue with that. Any help?

As described in error you are providing lambda expression instead of delegate. Use Action like this:
_dataHub.Subscribe("ReceiveMessage").Received += list =>
Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() =>
Messages.Add(list[0].ToString())));

Related

IdentityServer4: Reuse SqlConnection when calling the AddConfigurationStore extension method

In my case, I have several EF contexts that share the same database (ie, all the tables are on the same db) and I'd like to share the same SqlConnection amongst all contexts so that I can apply several changes inside the same transaction.
In order to achieve this, I've started by registering the SqlConnection with the following code:
services.AddScoped(sp => new SqlConnection(Configuration.GetConnectionString("DefaultConnection")));
After doing this, I've change one of the EF contexts so that it reuses the same connection:
services.AddDbContext<ApplicationDbContext>((provider, options) =>
options.UseSqlServer(provider.GetRequiredService()));
I need to do something similar when registering the configuration and operational store. Unlike the EF extension method, there isn't an overload which lets me pass an Action that references the options builder and the service provider:
services.AddIdentityServer()
.AddConfigurationStore(options =>
{
// HERE: no serviceprovider, how can I get the SqlConnection object???
options.ConfigureDbContext = builder =>
builder.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"),
sql => sql.MigrationsAssembly(migrationsAssembly));
})
builder.UseSqlServer does have an overload which lets me pass the connection, but how can I resolve the SqlConnection at runtime so that the same connection is shared across all contexts?
Thanks,
Luis
Answered by the man himself :)
Instead of using the CondigureDbContext property, you should use the ResolveDbContextOptions:
.AddConfigurationStore(options => {
options.ResolveDbContextOptions = (provider, builder) =>
builder.UseSqlServer(provider.GetRequiredService<Foo>().FooValue);
})

Winforms: Observable.Timer throws InvalidOperationException

I'm using winforms & reactive extension.
I'm using Observable.Timer inside my form.
When the timer fires, inside the callback an InvalidOperationException is raised when trying to invoke a method on any of the winform controls.
How can I fix this problem?
This is my code:
Observable.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(2))
.Subscribe((e) =>
{
XXXXX();
});
You need to use the ObserveOn(form) method.
Install nuget package "System.Reactive.Windows.Forms"
Add ObserveOn(form) before the Subscribe() method:
Observable
.Timer(TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(2))
.ObserveOn(this)
.Subscribe((e) =>
{
UpdateProcessStatus();
});

WPF: How to make Calls to Dispatcher.Invoke() Synchronous?

In my MVVM based Wix Managed Bootstrapper application, while handling different events, I'm trying to show the user a view to get some input. It looks like Burn events are executing Asynchronously because using Dispatcher.Invoke(), it is skipping or passing by the view and hitting the last event, i.e not waiting for this input task to finish.
Here is the event handler which needs to finish before hitting last one:
Please note that when MessageBox.Show is popped, it waits until we close it. While debugging, I see it actually switched to MissingSourceView and loaded MissingSourceViewModel, but then while skipping it, and executes ApplyComplete();
BootstrapperApplication.ResolveSource += (sender, e) => {
System.Windows.Forms.MessageBox.Show("Inside ResolveSource");
WixBootstrapperData.CurrentDispatcher.Invoke(((Action)(() =>
{
WixBootstrapperData.CurrentViewModel = new MissingSourceViewModel(WixBootstrapperData, InfoMessage);
})));
};
BootstrapperApplication.ApplyComplete += (sender, e) =>
{
WixBootstrapperData.BootstrapperApplicationModel.FinalResult = e.Status;
WixBootstrapperData.CurrentDispatcher.Invoke((Action)(() =>
{
InfoMessage = AppResource.MsgFinished;
WixBootstrapperData.CurrentViewModel = new FinishViewModel(WixBootstrapperData, InfoMessage);
}
));
};
I guess, I should use await and async with ResolveSource(), but I face errors like:
Error CS1061 'BaseViewModel' does not contain a definition for
'GetAwaiter' and no extension method 'GetAwaiter' accepting a first
argument of type 'Task' could be found (are you missing a using
directive or an assembly reference?)
Any idea how to make it wait for finishing inside ResolveSource() and then jump to wherever it wants?
Use this, and please tell if this solves your problem.
WixBootstrapperData.CurrentDispatcher.Invoke(((Action)(() =>
{
Task.Factory.StartNew(() => {
WixBootstrapperData.CurrentViewModel = new MissingSourceViewModel(WixBootstrapperData, InfoMessage);
}).RunSynchronously();
})));

Entity Framework async call blocking UI thread

I have been slowly trying to convert my code from using action delegates to the new Tasks in my WPF application. I like the fact that an await operation can run in the same method, greatly reducing the number of methods I need, enhancing readability, and reducing maintenance. That being said, I am having a problem with my code when calling EF6 async methods. They all seem to run synchronously and are blocking my UI thread. I use the following technologies/frameworks in my code:
.NET Framework 4.5
WPF
MVVM Light 5.2
Generic Unit Of Work/Repository Framework v3.3.5
https://genericunitofworkandrepositories.codeplex.com/
Entity Framework 6.1.1
SQL Server 2008 R2 Express
As an example, I have a LogInViewModel, with a command that executes after a button is clicked on my WPF application. Here is the command as initialized in the constructor:
LogInCommand = new RelayCommand(() => ExecuteLogInCommand());
Here is the command body:
private async void ExecuteLogInCommand()
{
// Some code to validate user input
var user = await _userService.LogIn(username, password);
// Some code to confirm log in
}
The user service uses a generic repository object that is created using MVVM Light's SimpleIoC container. The LogIn method looks like this:
public async Task<User> LogIn(string username, string password)
{
User user = await _repository.FindUser(username);
if (user != null && user.IsActive)
{
// Some code to verify passwords
return user;
}
return null;
}
And my repository code to log in:
public static async Task<User> FindUser(this IRepositoryAsync<User> repository, string username)
{
return await repository.Queryable().Where(u => u.Username == username).SingleOrDefaultAsync();
}
The SingleOrDefaultAsync() call is Entity Framework's async call. This code is blocking my UI thread. I have read multiple articles from Stephen Cleary and others about async await and proper use. I have tried using ConfigureAwait(false) all the way down, with no luck. I have made my RelayCommand call use the async await keywords with no luck. I have analyzed the code and the line that takes the longest to return is the SingleOrDefaultAsync() line. Everything else happens almost instantaneously. I have the same problem when making other async calls to the DB in my code. The only thing that fixes it right away is the following:
User user = await Task.Run(() =>
{
return _userService.LogIn(Username, p.Password);
});
But I understand this should not be necessary since the call I am making to the database is IO bound and not CPU bound. So, what is wrong with my application and why is it blocking my UI thread?
Your RelayCommand is not async.
LogInCommand = new RelayCommand(() => ExecuteLogInCommand());
Because there is no async/await your ExecuteLogInCommand will be called synchronously.
You got to change it to
LogInCommand = new RelayCommand(async () => await ExecuteLogInCommand());
so that the RelayCommand is called async too.
Your LogIn and FindUser (which, according to the guidelines, should be called LogInAsync and FindUserAsync) which are not supposed to work with the UI should use ConfigureAwait(false) on all awaits.
However all calls are synchronous until something really asynchronous is called. I suppose that would be SingleOrDefaultAsync.
If wrapping it in Task.Run makes such a difference, then, for some reason, SingleOrDefaultAsync must be running synchronously.

Exception while using ExecuteQuery() in Silverlight client object model

I have been developing a Silverlight user control for SharePoint using the Client Object model. Here is the coding
InitializeComponent();
ctx = ClientContext.Current;
Web web = ctx.Web;
ctx.Load(web, oweb => oweb.Title);
ctx.Load(web, oweb => oweb.Lists);
ctx.ExecuteQuery();
I heard tht SIlverlight supports both ExecuteQuery() and ExecuteQueryAsync() methods. But I'm getting an Exception message like this "he method or property that is called may block the UI thread and it is not allowed. Please use background thread to invoke the method or property, for example, using System.Threading.ThreadPool.QueueUserWorkItem method to invoke the method or property."
Can anyone tell me where am I going wrong and how to use ExecuteQuery() method ?? Thank you.
I might be off base here, but as I understand it, ExecuteQuery() requires you to create a thread so you aren't calling a stop to the UI thread when you invoke the method. The reason you use ExecuteQueryAsync is exactly that: ExecuteQueryAsync performs the operation on a seperate thread, then you just call back in to the UI thread using the dispather:
ctx.ExecuteQueryAsync(onQuerySucceeded, onQueryFailed);
...
private void onQuerySucceeded(object sender, ClientRequestSucceededEventArgs args)
{
this.Dispatcher.BeginInvoke((Action)(() =>
{
doStuff();
}));
}

Resources