I have a code where Application.DoEvents is causing problems and throwing exceptions. When a modal popup is opened and application has to wait for user activity , this code is written to execute in a loop to process background tasks until user's activity . Can someone tell me how can I trace (in debugging) what process is called from DoEvents which causes exception .
Here is some of the code . Can I trace what happens inside DoEvents :
private readonly AutoResetEvent Event = new AutoResetEvent(false);
while (_Event .WaitOne(20, false) == false)
{
Application.DoEvents();
Thread.Sleep(0);
}
Related
I have a bot with the following conversation scenario:
Send text to LUIS
LUIS intent calls context.Call(...) to launch a Dialog
This dialog terminates, save some info in the userData:
private static async Task storeBotData(IDialogContext context, BotData userData)
{
Activity activity = (Activity)context.Activity;
StateClient sc = activity.GetStateClient();
await sc.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, userData);
}
And after it call another dialog, again with context.Call(...).
Then the last dialog runs and terminates.
My problem is that when updating the user data at the end of the first dialog (step 3), I have the following exception in the Bot Framework Channel Emulator:
`Exception: The data is changed [File of type 'text/plain']`...
What happens here ? I think that when a dialog terminates, it call setUserData by itself, but I don't understand why I can't update userData anywhere in the code...
I have tried to catch the exception, but nothing is catched.. But I know that the userData is updated, because when I try to retrieve it back, it is updated...
Any help is welcome :)
Thanks
Botframework restores/saves state of conversation after each act of activity, so under the covers typical flow looks like the following:
[23:15:40] <- GET 200 getUserData
[23:15:47] <- GET 200 getConversationData
[23:15:47] <- GET 200 getPrivateConversationData
...
[23:16:42] <- POST 200 setConversationData
[23:16:42] <- POST 200 setUserData
[23:16:42] <- POST 200 setPrivateConversationData
As it is mentioned here : These botData objects will fail to be stored if another instance of your bot has changed the object already. So in your case the exception occurs at the termination of dialog, when framework calls setUserData by himself and figures out that the BotData has been changed already (by your explicit call of BotState.SetUserDataAsync). I suppose that's why you were not able to catch the exception.
Solution:
I used the following code and it fixed the issue:
private static void storeBotData(IDialogContext context, BotData userData)
{
var data = context.UserData;
data.SetValue("field_name", false);
}
The reason it works is that we modify the object of UserData but allow botFramework to "commit" it himself, so there is no conflict
I agree with #Artem (this solved my issue too, thanks!). I would just add the following guideline.
Use
var data = context.UserData;
data.SetValue("field_name", false);
whenever you have a IDialogContext object available, so you let the Bot Framework commit changes.
Use instead
StateClient sc = activity.GetStateClient();
await sc.BotState.SetUserDataAsync(activity.ChannelId, activity.From.Id, userData);
when you don't have an IDialogContext object, e.g. in the MessageController class.
This is basically a re-post of a previous question, but I've spent over 2 months stuck on this same issue and I haven't made any progress of any kind. Long story short, sometimes it fires and sometimes it doesn't. Sometimes it loads once, sometimes Outlook defaults it to "inactive" and there's nothing I seem to be able to do about it. When it DOES fire, it hangs up when trying to send the first email. So, I have old appointments outside of the date range I'm checking and the messagebox appears for those. When it gets to "new" appointments (within the date range), sometimes it pops up the first messagebox but hangs up trying to send the email. SOmetimes that first "good" messagebox fails to pop up. The last advice I got regarding this issue was to build a log file, but I couldn't figure out how/what good it was going to do me or honestly I wasn't even sure what I was going to need to log, and the gentleman who suggested it never responded to me when I asked. Thank you in advance for your help, this is easily one of the most frustrating things I've ever run in to as a developer.
using System;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Outlook = Microsoft.Office.Interop.Outlook;
using Office = Microsoft.Office.Core;
using Microsoft.Office.Interop.Outlook;
using System.Windows.Forms;
namespace OutlookAddIn1
{
public partial class ThisAddIn
{
//Outlook.Inspectors inspectors;
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
doStuff();
}
private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
{
}
#region VSTO generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InternalStartup()
{
this.Startup += new System.EventHandler(ThisAddIn_Startup);
this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
}
//https://msdn.microsoft.com/en-us/library/ms268866.aspx
private void doStuff()
{
Outlook.Application app = new Outlook.Application();
Thread.Sleep(30000); //120 seconds - was 120000
DateTime firstRun = DateTime.Now; //So we can check every 24 hours? Maybe once initially as well.
DateTime lastRun = DateTime.Now;//.AddHours(1); //We're going to compare this to firstRun
bool whileTrue = true;
//int test = 0;
try
{
while (whileTrue)
{
if (whileTrue == true)//(firstRun > lastRun.AddDays(1))
{
Outlook.MAPIFolder calendarFolder = Application.Session.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar);
Outlook.Items outlookCalendarItems = calendarFolder.Items;
outlookCalendarItems.IncludeRecurrences = true; //was true
List<Outlook.AppointmentItem> lst = new List<Outlook.AppointmentItem>();
foreach (Outlook.AppointmentItem item in outlookCalendarItems)
{
lst.Add(item);
//We can probably just handle logic in here without the second for loop that comes next
}
foreach (Outlook.AppointmentItem x in lst)
{
DateTime startDate = DateTime.Now.AddDays(1);
DateTime endDate = DateTime.Now.AddDays(5);
DateTime apptDate = x.Start;
if (x.Subject.ToLower().Contains("telos"))
{
MessageBox.Show("X: " + x.Start + "XYZ: " + x.Subject);
if (x.Start > startDate && x.Start < endDate)
{
Microsoft.Office.Interop.Outlook.MailItem email = app.CreateItem((OlItemType.olMailItem));
//Outlook.MailItem mail = (Outlook.MailItem)Globals.ThisAddIn.Application.CreateItem(Outlook.OlItemType.olMailItem);
//Outlook.Recipient recipient = Globals.ThisAddIn.Application.Session.CreateRecipient("cindy#soundstewardship.com");
//email.Sender = recipient.AddressEntry;
//Outlook.Recipient recipient = app.Session.CreateRecipient("someone#example.com");
//email.Sender = recipient.AddressEntry;
//email.SentOnBehalfOfName = "someone#example.com";
email.Display(true); //was false
email.Subject = "You have a new appointment";
email.Importance = Outlook.OlImportance.olImportanceLow;
email.To = Application.Session.CurrentUser.AddressEntry.Address; //Current email address.
email.Body = "This email was automatically generated to remind you have an upcoming appointment on: " + x.Start.ToString();
email.Save();
email.Close(OlInspectorClose.olSave);
//((Outlook._MailItem)email).Send();
//email.Send();
//((Outlook._MailItem)mailItem).Send();
}
}
}
lastRun = DateTime.Now;
whileTrue = false;
}
else
{
/*
Outlook.MailItem email = new Outlook.MailItem();
email.Subject = "This is only a test.";
email.To = Application.Session.CurrentUser.AddressEntry.Address; //Current email address.
email.Body = "This is only a test.";
//email.Send();
((Outlook._MailItem)email).Send();
* */
}
}
}
catch (System.Exception e) //Microsoft.Office.Interop.Outlook.Exception e
{
MessageBox.Show(e.InnerException.ToString());
}
finally
{
app.Quit();
}
}
#endregion
}
}
First of all, there is no need to create a new Outlook Application instance in the code. You need to use the Application property of the add-in class.
At startup, I need it to read all appointments whose subject contains a certain string
Don't use the foreach for iterating over all items in the folder. Instead, you need to use the Find/FindNext or Restrict methods of the Items class. You may read more about these methods in the following articles (the sample code is included):
How To: Retrieve Outlook calendar items using Find and FindNext methods
How To: Use Restrict method in Outlook to get calendar items
When you are done I'd recommend using the Resolve or ResolveAll methods of the Recipient(s) class to resolve all recipients against the address book.
Also, like 75% of the time this addin loads directly as "inactive" and doesn't fire.
Microsoft Office applications can disable add-ins that behave unexpectedly. If an application does not load your add-in, the application might have hard disabled or soft disabled your add-in.
Hard disabling can occur when an add-in causes the application to close unexpectedly. It might also occur on your development computer if you stop the debugger while the Startup event handler in your add-in is executing.
Soft disabling can occur when an add-in produces an error that does not cause the application to unexpectedly close. For example, an application might soft disable an add-in if it throws an unhandled exception while the Startup event handler is executing.When you re-enable a soft-disabled add-in, the application immediately attempts to load the add-in. If the problem that initially caused the application to soft disable the add-in has not been fixed, the application will soft disable the add-in again. Read more about that in the How to: Re-enable an Add-in That Has Been Disabled article.
Also Outlook 2013 monitors add-in performance metrics such as add-in startup, shutdown, folder switch, item open, and invoke frequency. Outlook records the elapsed time in milliseconds for each performance monitoring metric. For example, the startup metric measures the time required by each connected add-in during Outlook startup. Outlook then computes the median startup time over 5 successive iterations. If the median startup time exceeds 1000 milliseconds (1 second), then Outlook disables the add-in and displays a notification to the user that an add-in has been disabled. The user has the option of always enabling the add-in, in which case Outlook will not disable the add-in even if the add-in exceeds the 1000 millisecond performance threshold. See Performance criteria for keeping add-ins enabled for more information.
Why would you sleep on the main Outlook thread? And then loop through all items in the folder instead of using Items.Restrict or Items.Find/FindNext?
How to debug Window service methods without attach process .
#if (!DEBUG)
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new BirthdayService()
};
ServiceBase.Run(ServicesToRun)`#else
// Debug code: this allows the process to run as a non-service.
// It will kick off the service start point, but never kill it.
// Shut down the debugger to exit
BirthdayService service = new BirthdayService();
service.InitializeUsersTable();
service.GetUserAndSendMail();
// Put a breakpoint on the following line to always catch
// your service when it has finished its work
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
#endif
To start off with, this might be tagged as a duplicate of the following thread:
Wait for HttpWebRequest.BeginGetResponse to finish in Windows Phone 7, however, the responses in that thread did not help me get over my problem.
To begin with, I am collecting user data on the UI Thread in order to process application registration, where I also have an instance of ManualResetEvent:
private static ManualResetEvent registrationEvent = new ManualResetEvent(false);
I have another thread which handles the registration process (and includes the HttpWebRequest.BeginGetResponse() and its corresponding callback method.)
Thread t = new Thread(() => RegistrationHandler.sendRegistrationData(url));
t.Start();
Right after this call, I block the current (UI) thread with a call to
registrationEvent.WaitOne();
//Process the response, update some UI elements and navigate to a different page.
httpSessionCompleted(response);
Once the thread handling the registration process starts, I am instantiating HttpWebRequest and invoking the BeginGetResponse() method on it.
try
{
HttpWebRequest request = HttpWebRequest.CreateHttp(url);
request.Method = "POST";
request.ContentType = mimeType;
request.BeginGetResponse(new AsyncCallback(GetRequestCallback), request);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in sendData(): {0}", ex.Message);
}
Now the issue is that the callback method (code below) is never invoked, and the application just freezes. There also doesn't seem to be any exception(s) thrown either.
try
{
HttpWebRequest request = (HttpWebRequest)asyncResult.AsyncState;
if (request != null)
{
using (HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asyncResult))
{
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
String result = reader.ReadToEnd();
Globals.HostResponse = result;
//Signalling the calling thread to continue execution
RegistrationPage.RegistrationEvent.Set();
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in GetRequestCallback(): {0}", ex.Message);
}
I ideally want my application to continue from httpSessionCompleted() after the callback method finishes execution. Can someone please help me with some guidance/suggestions?
Sorry for being verbose. Thanks!
You should not block UI thread, use callback pattern instead. Look at this: Windows Phone 7 - wait for Webclient to complete . Hope this helps
I'm using the odata client generator (DataSvcUtil.exe) in a Windows Phone 7 application. Retrieving entities and collections is fine as is updating an existing entity. But when I try to add a new entity, I get a NotSupportedException. Here's my code.
private void Button_Click(object sender, RoutedEventArgs e)
{
Drinks d =new Drink();
d.BarCode = "1234567890";
d.Description = "Test Drink";
d.Quantity = -1;
context.AddToDrinks(d);
context.BeginSaveChanges(SaveChangesOptions.Batch, OnChangesSaved, context);
}
private void OnChangesSaved(IAsyncResult result)
{
Dispatcher.BeginInvoke(() =>
{
try
{
var something = result.AsyncState;
context = result.AsyncState as DrinkTrackerModelContainer;
// Complete the save changes operation and display the response.
ShowSaveResponse("Drink Logged!", context.EndSaveChanges(result));
}
catch (DataServiceRequestException ex)
{
ShowSaveResponse("Error Logging Drink", ex.Response);
}
catch (InvalidOperationException ex)
{
ShowSaveResponse(ex.Message, null);
}
}
);
}
As soon as EndSaveChanges is called, I get the
NotSupportedException.
EDIT: I used fiddler and saw that I was in fact getting a different exception from the service. That exception data was not being shown in the debugger. Once I corrected the actual exception, the insert worked fine.
I think you have first chance exceptions turned on which is causing an internal exception thrown by the client library to surface as an exception. Try turning off First Chance Exceptions in the "Exceptions" menu in VS and running the app.
As you mentioned in your edit, the NotSupportedException was a red herring. I think that when debugging a phone app you will hit the NotSupportedException even if you have cleared the setting to break on unhandled CLR exceptions.
If you continue(F5), you'll hit an actual DataServiceRequestException exception. If it doesn't have enough information to debug it, you can follow the steps in this post to get more detailed information in the exception: http://blogs.msdn.com/b/phaniraj/archive/2008/06/18/debugging-ado-net-data-services.aspx
I ran into the same problem yesterday, and after following the steps in the blog I was able to successfully debug the problem.