The calling thread cannot access this object because a different thread owns it - wpf

i have a problem whenever i Refresh the prograss bar i get the error The calling thread cannot access this object because a different thread owns it
how can i remove it
shashank
backgroundWorker12 = new BackgroundWorker();
timer1.Enabled = true;
//cancel any async processes running for the background worker
//backgroundWorker1.CancelAsync();
backgroundWorker12.DoWork += (s, args) =>
{
BackgroundWorker worker2 = s as BackgroundWorker;
worker2.WorkerReportsProgress = true;
float percentageDone = 20f;
//check if the user status and update the password in xml
CheckUseridPwd();
//call the function to sync the wall chart data
//call the function to sync event relate data
percentageDone = 100f;
ValidateLogin2(txtUserID.Text.Trim(), txtPassword.Password.Trim(), -1);
worker2.ReportProgress((int)percentageDone);
};`

This bit looks like it's using UI controls from the wrong thread:
ValidateLogin2(txtUserID.Text.Trim(), txtPassword.Password.Trim(), -1);
I suggest you capture the user and password in local string variables above the code which adds the event handler - you can use those captured variables within your delegate. That way everything should be on the right thread:
backgroundWorker12 = new BackgroundWorker();
timer1.Enabled = true;
string user = txtUserID.Text.Trim();
string password = txtPassword.Password.Trim();
backgroundWorker12.DoWork += (s, args) =>
{
// ... same code as before up to here
ValidateLogin2(user, password, -1);
worker2.ReportProgress((int)percentageDone);
};

See if you can use the RunWorkerCompleted event of the BackgroundWorker, since you're accessing the UI only after progress is 100% i.e. done..
Then you wouldn't have to worry about thread-affinity of WPF UI controls - since the event handler is invoked again on the right/ UI Thread.
The other option (if you need to access the UI controls before the work is complete) is to cache the object
returned by Dispatcher.CurrentDispatcher on the UI Thread before the work starts and then use object.Invoke to marshal to the right thread from the thread pool thread that is executing your DoWork handler. See some code here.

Have you tried invoking ValidateLogin2
you can either do it directly from your code shown, or in ValidateLogin2 check if the method itself requires invoking. If not, go ahead and validate, but if it does, then have it invoke itself
void ValidateLogin2(...)
{
if (this.InvokeRequired)
{
//Invokes itself if required
BeginInvoke(new MethodInvoker(delegate(){ValidateLogin2(...);}));
}
else
{
//validate login here
}
}

Related

Creating a new UI thread while calling methods on the original thread

I am in a similar situation as this poster (What's the best way to create a new UI thread and call back methods on the original thread?)
I have an API object which I would like to perform lengthy calculations on, however any properties or methods of this object must be accessed on the current thread (which is the UI thread) or else I get "Accessing disposed TPS.NET DataObject" exceptions
Is there an elegant way of accomplishing this using F# async workflows or will I be stuck managing thread dispatchers as in his solution.
For reference, here is his solution to the issue:
public class Plugin
{
public void Run(Context context)
{
// Get the application's UI thread dispatcher
var dispatcher = Dispatcher.CurrentDispatcher;
// Create a dispatcher frame to push later
var frame = new DispatcherFrame();
// Create a new UI thread (using an StaTaskScheduler)
Task.Factory.StartNew(async () =>
{
var window = new MyWindow();
// The Click event handler now uses the original
// thread's dispatcher to run the slow method
window.MyButton.Click += async (o, e) =>
await dispatcher.InvokeAsync(() => context.SlowMethod());
window.ShowDialog();
// When the window is closed, end the dispatcher frame
frame.Continue = false;
}, CancellationToken.None, TaskCreationOptions.None, new StaTaskScheduler(1));
// Prevent exiting this Run method until the frame is done
Dispatcher.PushFrame(frame);
}
}
Without know the exact details I would suggest having the Click handler on the main thread and do the following:
Copy any data needed off the UI into an F# record and passes this into an async workflow
Return immediately after putting the UI into a 'loading' state
The following code is untested but should put you on the right track:
//Get the context of the UI
let context = System.Threading.SynchronizationContext.Current
//Gather any needed data from the UI into immutable F# records
//Put the UI into a 'loading' state
async {
// Do work on a different thread
do! Async.Sleep 1000
let x = 1
// Switching back to the UI
do! Async.SwitchToContext context
//Update UI
return ()
}
|> Async.Start
This link should also provide some useful information http://tomasp.net/blog/async-non-blocking-gui.aspx/
EDIT:
If you need to go back and forth between the UI thread and a background thread to gather additional information in the async workflow you can make alternating calls between do! Async.SwitchToThreadPool() and do! Async.SwitchToContext context

Closing the New Window on a new Thread (WPF)

Hi I had posted a question along these lines recently but this is now a little more specific to my requirements. So, I have an Application where the user needs to log in. The log in process can take some time so I decided to put up a little animated GIF to show it is doing something. Sounds simple...!!??
I noticed soon that the login process was freezing the animation so I thought, I will put the login process on its own thread. I had countless instances of it referencing objects on the UI Thread so thought I would try the other way round and have the Image display on a new thread. Same issue - so I decided to create a new window containing the image, format it accordingly and display this as a new thread! Simple! That (bit) worked... I click to login, animation appears and disappears onces login is complete. So the Thread variable is set as global one:
Friend g_thLoading As Thread
And when the Login button is clicked I have the following:
g_thLoading = New Thread(AddressOf LoginSplashScreen)
g_thLoading.SetApartmentState(ApartmentState.STA)
g_thLoading.IsBackground = True
g_thLoading.Name = "LoginThread"
g_thLoading.Start()
VerifyLogin() 'Process that takes a while...
g_thLoading.Abort()
Then the method that is called in the new thread:
Sub LoginSplashScreen()
Dim SplashScreenWin As New SplashScreen()
Try
SplashScreenWin.ShowDialog()
System.Windows.Threading.Dispatcher.Run()
Catch ex As Exception
SplashScreenWin.Close()
SplashScreenWin = Nothing
End Try
End Sub
This works - but not if I have to click the button more than once. However If (for example) the user enters the wrong credentials, clicks login (the above processes and completes) they are prompted to re-enter - click the login button again... but this time, the window doesnt display (but oddly does appear in the Task Bar)... Then the application is forced to close (nothing in debug on why that is).
I am confident that the Dialogue Window is closing correctly after the first instance as i) it is no longer in the Task Bar and secondly I have put some checks on the Windows Close event. I am fairly confident that the created Thread is closed after the first instance as I can see it drop off from the Thread Window in Visual Studio... So - I am at a total loss. I have also tried the Join function on the thread but this just hangs the process before it gets to g_thLoading.Abort()
I am open to any advice on how I can go about achieving my end goal... whether it is expanding on what I have done here or another suggestion altogether. I have messed around with the Background Worker but not had much more luck there.
Use the BackgroundWorker class to implement your long running processes. The class allows you to specify code that will run on a background thread (in the DoWork event handler), code that will run during "updates" on the thread that created the BackgroundWorker in the ProgressChanged event handler, and code that will run when the process completes, again on the thread that created the BackgroundWorker in the RunWorkerCompleted event handler.
Using it goes something like this:
private class LoginParameters {
public string Name { get; set; }
public string Password { get; set; }
// Any other properties needed
}
// Make this a property of your form.
BackgroundWorker LoginWorker { get; set; }
// Somewhere in your UI code after the user clicks the "login button"
LoginWorker = new BackgroundWorker();
LoginWorker.WorkerReportsProgress = true;
LoginWorker.WorkerSupportsCancellation = true; // Can set to false if you don't allow the operation to be cancelled.
LoginWorker.DoWorker += DoLogin;
LoginWorker.ProgressChanged += ReportProgress;
LoginWorker.RunWorkerCompleted += LoginFinished;
LoginParameters login = new LoginParameters {
// Code to initialize everything here
};
LoginWorker.RunWorkerAsync(login);
// Put this in the click event handler for the Cancel button, if you have one
if ( LoginWorker != null )
LoginWorker.CancelAsync();
private void DoLogin(object sender, DoWorkEventArgs e) {
BackgroundWorker worker = (BackgroundWorker) sender;
LoginParameters login = (LoginParameters) e.Argument;
// Your logic to process the login goes here. It should periodically do the following to check to see if the user clicked the cancel button:
if ( worker.CancellationPending ) {
e.Cancel = true;
return;
}
// When you want to update the UI, do this:
worker.ReportProgress( percentComplete, objectWithOtherDataToWriteToTheUI );
// When you're done, just return.
}
private void ReportProgress(object sender, ProgressChangedEventArgs e) {
// Your code to extract the data you need to update the display from the arguments & to then update the display goes here. Remember, this runs on the UI thread
}
private void LoginFinished( object sender, RunWorkerCompletedEventArgs e ) {
if (e.Cancelled == true)
// Your code to inform the user of the cancellation here
else if (e.Error != null)
// All unhadgled exceptions throws by the DoWork event handler end up here
// Your code to inform the user of the error here
else {
// Your code to inform the user of the success goes here.
// Remember, this runs on the UI thread.
// I recommend you set the form BackgroundWorker property to null after its finished, as you can't reuse it after its finished.
LoginWorker = null;
}
}
Sorry this is in C# if you're looking for VB.NET, but it shouldn't be hard to translate.

WPF + PRISM - Cannot 'LoadModule' in separate thread

I have a WPF application in PRISM architecture.
I have a 'Login View' that is shown in the 'Main Region' when the app loads.
When the user presses 'Login' - I connect to a WCF service, authenticate the user, and get a list of roles for that user from the service.
Then - according to the user's roles - I load different modules, using the 'Module Manager'.
Problem is - I want all the work after the 'Login' button is pressed to be done in a separate thread, because it might take time to connect to the service etc, and I don't want the UI to be frozen.
But - if I put the code to 'connect, authenticate, get roles, load modules' in a separate thread - I get an exception when I call '_moduleManager.LoadModule' that says:
The calling thread must be STA, because many UI components require this.
How can I solve this ?
I have tried different solutions.
I have tried to set the new thread's 'Apartment State = STA' and it didn't help.
I thought about saving the 'Dispatcher' object in the constructor of the View-Model, and then do 'dispatcher.Invoke' when I call 'LoadModule', but that is bad design (View-Model should not use Dispatcher, and also it is bad for testing).
Any ideas how I can solve this ??
Only the 'LoadModule' gives me grief, all the other stuff works fine.
.
[Update] - Added Code Sample :
[Export]
public class LoginViewModel : NotificationObject
{
[ImportingConstructor]
public LoginViewModel(IRegionManager regionManager, IModuleManager moduleManager)
{
this.LoginCommand = new DelegateCommand(LoginExecute, LoginCanExecute);
this._regionManager = regionManager;
this._moduleManager = moduleManager;
}
private void LoginExecute()
{
IsBusy = true; // Set this to 'true' so controls go disabled
LoginStatus = ""; // Clear the 'login status' string
Thread loginThread = new Thread(new ThreadStart(LoginWork));
loginThread.SetApartmentState(ApartmentState.STA);
loginThread.Start();
}
private void LoginWork()
{
ParamsToGetRoles param = new ParamsToGetRoles
{
Username = Username,
InputtedPassword = Password
};
try
{
// Connect to the secure service, and request the user's roles
_clientSecure = new AuthenticationServiceClient("WSHttpBinding_MyService");
_clientSecure.ClientCredentials.UserName.UserName = param.Username;
_clientSecure.ClientCredentials.UserName.Password = param.InputtedPassword;
_clientSecure.ChannelFactory.Faulted += new EventHandler(ChannelFactory_Faulted);
var local = _clientSecure.ChannelFactory.CreateChannel();
_clientSecure.GetRolesCompleted += new EventHandler<GetRolesCompletedEventArgs>(clientSecure_GetRolesCompleted);
_clientSecure.GetRolesAsync(param);
}
catch (Exception ex)
{
Console.WriteLine("Exception : " + ex.Message.ToString());
}
}
void clientSecure_GetRolesCompleted(object sender, GetRolesCompletedEventArgs e)
{
if (e.Error == null)
{
_clientSecure.Close();
LoginSuccess(e.Result.UserRoles);
}
else
{
LoginFailure("Unable to authenticate");
}
_clientSecure = null;
}
private void LoginSuccess(List<UserTypeEnum> rolesOfAuthenticatedUser)
{
LoginStatus = "Success";
if (rolesOfAuthenticatedUser.Contains(UserTypeEnum.Administrator))
{
// This is what throws the exception !
// This is called by the 'EndInvoke' of the 'GetRoles' operation,
// Which was called in the 'LoginWork' function which was run on a separate thread !
_moduleManager.LoadModule(WellKnownModuleNames.ModuleAdmin);
}
NavigateToMainMenu();
this.IsBusy = false;
}
}
You should attach the debugger and inspect the threads window with a breakpoint set at clientSecure_GetRolesCompleted. I'm pretty sure it is not being called from the loginThread: while LoginWork does run in the loginThread, it then adds an eventhandler to the completion event of an async operation. Async = runs in yet another thread.
So what probably happens:
LoginExecute executes in the UI thread
starts a seperate thread B to run LoginWork
calls GetRolesAsync so start a thread C (which is not STA) to get the roles
thread C eventually calls 'clientSecure_GetRolesCompleted', not thread B
So, you do not need a seperate thread for LoginWork since the actual work is already done as an async operation. To get around the loading issue, either try to make the 'get roles' thread STA, or better, use a dispatcher so LoginSuccess gets invoked on the UI thread.

Calling a webservice synchronously from a Silverlight 3 application?

I am trying to reuse some .NET code that performs some calls to a data-access-layer type service. I have managed to package up both the input to the method and the output from the method, but unfortunately the service is called from inside code that I really don't want to rewrite in order to be asynchronous.
Unfortunately, the webservice code generated in Silverlight only produces asynchronous methods, so I was wondering if anyone had working code that managed to work around this?
Note: I don't need to execute the main code path here on the UI thread, but the code in question will expect that calls it makes to the data access layers are synchronous in nature, but the entire job can be mainly executing on a background thread.
I tried the recipe found here: The Easy Way To Synchronously Call WCF Services In Silverlight, but unfortunately it times out and never completes the call.
Or rather, what seems to happen is that the completed event handler is called, but only after the method returns. I am suspecting that the event handler is called from a dispatcher or similar, and since I'm blocking the main thread here, it never completes until the code is actually back into the GUI loop.
Or something like that.
Here's my own version that I wrote before I found the above recipe, but it suffers from the same problem:
public static object ExecuteRequestOnServer(Type dalInterfaceType, string methodName, object[] arguments)
{
string securityToken = "DUMMYTOKEN";
string input = "DUMMYINPUT";
object result = null;
Exception resultException = null;
object evtLock = new object();
var evt = new System.Threading.ManualResetEvent(false);
try
{
var client = new MinGatServices.DataAccessLayerServiceSoapClient();
client.ExecuteRequestCompleted += (s, e) =>
{
resultException = e.Error;
result = e.Result;
lock (evtLock)
{
if (evt != null)
evt.Set();
}
};
client.ExecuteRequestAsync(securityToken, input);
try
{
var didComplete = evt.WaitOne(10000);
if (!didComplete)
throw new TimeoutException("A data access layer web service request timed out (" + dalInterfaceType.Name + "." + methodName + ")");
}
finally
{
client.CloseAsync();
}
}
finally
{
lock (evtLock)
{
evt.Close();
evt = null;
}
}
if (resultException != null)
throw resultException;
else
return result;
}
Basically, both recipes does this:
Set up a ManualResetEvent
Hook into the Completed event
The event handler grabs the result from the service call, and signals the event
The main thread now starts the web service call asynchronously
It then waits for the event to become signalled
However, the event handler is not called until the method above has returned, hence my code that checks for evt != null and such, to avoid TargetInvocationException from killing my program after the method has timed out.
Does anyone know:
... if it is possible at all in Silverlight 3
... what I have done wrong above?
I suspect that the MinGatServices thingy is trying to be helpful by ensuring the ExecuteRequestCompleted is dispatched on the main UI thread.
I also suspect that your code is already executing on the main UI thread which you have blocked. Never block the UI thread in Silverlight, if you need to block the UI use something like the BusyIndicator control.
The knee-jerk answer is "code asynchronously" but that doesn't satisfy your question's requirement.
One possible solution that may be less troublesome is to start the whole chunk of code from whatever user action invokes it on a different thread, using say the BackgroundWorker.
Of course the MinGatServices might be ensuring the callback occurs on the same thread that executed ExecuteRequestAsync in which case you'll need to get that to run on a different thread (jumping back to the UI thread would be acceptable):-
Deployment.Current.Dispatcher.BeginInvoke(() => client.ExecuteRequestAsync(securityToken, input));

Update Label while processing in Windows Forms

What is the best way to update a label on a Windows Forms application while processing?
I have a loop that does some processing to files on the user's system when the user clicks a button.
foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
{
// Do processing
// Show progress bar
// Update Label on Form, "f.Name is done processing, now processing..."
}
What would be some sample code?
What exactly is this called? Is it threading or delegates?
A quick fix for you would be:
Label1.Text = f.Name + " is done processing, now processing...";
Label1.Refresh();
You really want to avoid DoEvents, otherwise you'll have problems if your user repeatedly presses buttons on your form.
You should be doing this on another thread, and then updating your UI thread from that thread. You are blocking further processing by performing this work on the UI thread.
If you can't move this code to the UI thread, then you could always call Application.DoEvents, but I strongly suggest you explore these options first:
System.ComponentModel.BackgroundWorker
System.Threading.ThreadPool
System.Threading.Thread
System.Threading.Tasks namespace
You'll need to get your data from one thread to the other. This can be done in a couple of ways...
First, your "background" thread could update some kind of "CurrentStatus" string variable that it changes as it goes along. You could then put a timer on your form that would then grab the CurrentStatus variable and update the label with it.
Second, you could simply invoke the operation from the background thread to the UI thread with a delegate using the InvokeRequired property of the label control. So for example...
private delegate void UpdateStatusDelegate(string status);
private void UpdateStatus(string status)
{
if (this.label1.InvokeRequired)
{
this.Invoke(new UpdateStatusDelegate(this.UpdateStatus), new object[] { status });
return;
}
this.label1.Text = status;
}
You can call that UpdateStatus() method from any thread (UI or background), and it will detect whether or not it needs to invoke the operation on the main UI thread (and if so, does it).
To actually set up the thread, you can do so like this:
private void StartProcessing()
{
System.Threading.Thread procThread = new System.Threading.Thread(this.Process);
procThread.Start();
}
private void Process() // This is the actual method of the thread
{
foreach (System.IO.FileInfo f in dir.GetFiles("*.txt"))
{
// Do processing
// Show progress bar
// Update Label on Form, "f.Name is done processing, now processing..."
UpdateStatus("Processing " + f.Name + "...");
}
}
Then when the user clicks the "GO" button you'll simply call StartProcessing().
If your processing is lengthy do it in a backgroundworker thread.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
I also recommend to use :
Application.DoEvents();
Processes all Windows messages currently in the message queue.

Resources