Hi Im new at Silverlight/async programming
Situation: Silverlight app as a webresource that make CRUD operations
Problem: The entity have a plugin step registered to it as Synchronous. Then in silverlight when the code execute the EndSaveChages(results) method I get a SystemException.
The message received is:
The current object did not originate the async result.Parameter name:
asyncResult
I tried using a lock, Thread.Sleep, While and the Dispatcher but nothing help. There is a way to hold the process until I receive the asycResult?
Code:
private void OnUpdateRecordComplete (IAsyncResult result)
{
try
{
while (!result.IsCompleted)
{
}
Thread.Sleep(1000);
xrmsm_scores updatedRecord = result.AsyncState as xrmsm_scores;
context.EndSaveChanges(result);
// MessageBox.Show("Save Completed!");
MessageBox.Show(updatedRecord.xrmsm_studentsName.Trim() + "'s Grade has been updated!");
//MessageBox.Show("HUGE SUCCESS!");
}
catch (DataServiceRequestException se)
{
MessageBox.Show("The score information could not be saved.\nReason: " + getXMLError(se), "Error!", MessageBoxButton.OK);
studentName = string.Empty;
}
catch (SystemException se)
{
isSaved = true;
//string error = se.Message.Replace('"', '\'').Replace("\r\n", #"\n");
//MessageBox.Show("OnUpdateRecordComplete SystemExeption Catch: " + error);
//It always goes on catch because we are not using MVC System
//It saves it anyways :P
//MessageBox.Show("OnCreateRecordComplete");
//syncContext.Send(new SendOrPostCallback(showErrorDetails), se);
}
}
You shouldn't have to do sleeping or waiting. My understanding is that the complete event handler is only called once async call returns.
Have you seen this sample? It should help to guide you in the right direction.
Sample: Create, Retrieve, Update and Delete Using the REST Endpoint with Silverlight
Related
I am using wakefull intent service and works very fine. But currently i see that many times my intent service is in wait satate.I found that problem is with javamail as it goes in deadlock state when ever internet connection is resets.
I search option to intrupt operation java mail but can't find any solution.I have set IMAP,SMTP Time out property but it is not working.
if(msg1[0]!= null)
{
if(!Mail.store.isConnected() || f== null)
{
Log.v(tag, "StoreNot Connected");
m = new Mail(username, password);
f =m.getlable("Message_"+nick);
Log.v(tag, "Store Connected");
}
try{
Log.v(tag, "Sending Mail");
//Get DeadLock Hear
f.appendMessages(msg1);
sucess_flag=1;
Log.v(tag, "Mail Send");
}
catch(Exception e)
{
e.printStackTrace();
}catch(Throwable e)
{
e.printStackTrace();
}
}
So now i am looking for an option to restart or kill the current intent service.
Is there any option for this?
If not then is it a good idea to create theads from intentservice and kill them instead?
Try this:
Intent GPSService = new Intent(context, TrackGPS.class);
context.stopService(GPSService);
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.
I have a lightswitch application needs to generate Crystal Report from it's WCF Ria. In the development runtime I am able to generate correctly without errors, but when I push it to release environment it prompt error - invalid cross-thread access.
I've read some articles already and it is very likely Silverlight UI Thread problem
partial void GenerateReport_Execute()
{
try
{
GenerateCrystalReport.Load();
var temp = DataWorkspace.QUMCrystalReportDomainData.GenerateCrystalReport(SearchQuery.SelectedItem.GroupId, sQuarter, sYear, eQuarter, eYear);
System.Windows.Deployment.Current.Dispatcher.BeginInvoke(delegate()
{
var uri = new Uri("C:\\Temp\\ReportTest.pdf", UriKind.RelativeOrAbsolute);
if (AutomationFactory.IsAvailable)
{
var shell = AutomationFactory.CreateObject("Shell.Application");
shell.ShellExecute(uri.ToString());
}
else if (!System.Windows.Application.Current.IsRunningOutOfBrowser)
{
HtmlPage.Window.Navigate(uri, "_blank");
}
else
{
throw new InvalidOperationException();
}
});
}
catch ( Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
Am I doing incorrectly? please help me identify this.
Thanks in Advance
Sam
Answering my question, basically that messagebox at bottom is causing the UI problem.
Lightswitch's dispatcher is not same as wpf's dispatcher(what that messagebox uses), please correct if I'm wrong
I have a Windows Phone 7 application built with silverlight. This application has been deployed. I've noticed in the log files that occasionally, my user's actions throw a "NotSupportedException". I have not been able to produce this. However, because of my logs, I know that it is happening in the Execute method shown here:
public void Execute()
{
try
{
// 1. Build the query
string serviceUrl = GetServiceUrl;
// 2. Asynchronously execute the query using HttpWebRequest
WebRequest request = HttpWebRequest.Create(serviceUrl);
request.BeginGetResponse(new AsyncCallback(ServiceRequest_Completed), request);
} catch (Exception ex)
{
LogException(ex, "1");
}
}
private void ServiceRequest_Completed(IAsyncResult result)
{
try
{
// 1. Get the response from the service call
WebRequest request = (WebRequest)(result.AsyncState);
WebResponse response = request.EndGetResponse(result);
// 2. Do stuff with response
}
catch (Exception ex)
{
LogException(ex, "2");
}
}
I know it is happening in the Execute method because the "1" is written in the log file instead of the "2" My question is, what would cause this? I looked at the MSDN documentation and it looks like I'm doing what I should be doing. Like I said, I can't reproduce it locally. But I do know that it is happening regularly by different users because of the log files.
There is a previous question with a very similar title - https://stackoverflow.com/questions/4053197/httpwebrequest-leads-me-to-system-notsupportedexception
The answer to that problem seems to have been using ServiceRequest_Completed instead of new AsyncCallback(ServiceRequest_Completed)
After some digging into exception handling in silverlight and reading some useful blogs like this
Silverlight exception handling using WCF RIA Services and WCF Services I ended up implementing similar idea in the App.xaml.cs to show an error page and call another wcf service method to log the error to the event viewer:
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
if (!System.Diagnostics.Debugger.IsAttached)
{
var errorPage = new Error();
errorPage.Show();
string errorMsg = string.Format("{0} {1}", e.ExceptionObject.Message, e.ExceptionObject.StackTrace);
EventHandler<WriteIntoEventLogCompletedEventArgs> callback = (s, ev) =>
{
bool result = ev.Result;
};
(new ServiceProxy<ApplicationServiceClient>()).CallService<WriteIntoEventLogCompletedEventArgs>(callback, errorMsg);
e.Handled = true;
}
}
and this is what I have in Error.xaml.cs:
private void OKButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
}
that basically will close the error page when user clicks on OK.
Everything works fine most of the cases.The problem happens when one of the callbacks to the wcf service cause an exception.The error page will be shown nicely and when user clicks ok, error page will get closed. But the background is still showing the busy indicator and the original service callback is still waiting for the response.I need to somehow terminate it.
I would be appriciative if anybody could help.
Thanks,
Sil
--
Thanks a lot for your helpful reply.I used the same idea and in the original service callback method added a code to check e.Error and if it is not null,close the window(it is a child window) with the busyindicator and everything works perfect now. Thanks again. Sil
My guess is that the original service callback may be completing but in an error condition. You may need to detect the error condition and set the IsBusy property of the busyindicator back to False.
Couple of things to check
Is the original service callback atleast returning successfully? You can check this by placing a breakpoint into the original service callback method.
Have you correctly handled the error condition in your callback method. For example -
void proxy_GetUserCompleted(object sender, GetUserCompletedEventArgs e)
{
if (e.Error != null)
{
getUserResult.Text = "Error getting the user.";
}
else
{
getUserResult.Text = "User name: " + e.Result.Name + ", age: " + e.Result.Age + ", is member: " + e.Result.IsMember;
}
}
Reference - http://msdn.microsoft.com/en-us/library/cc197937(v=VS.95).aspx