I am getting an undefined null pointer exception if I try this. (Removing the thread code solves it). Isn't it possible to spawn a new thread from a setter? If so, why not? I am used to doing it this way from Java. Thank you
EDIT: The actual stripped down code:
public string AuthToken {
set {
this.authToken = value;
var RunOnNewThread = new Thread(() =>
{
Console.WriteLine("Test");
} );
RunOnNewThread.Start();
}
get { return this.authToken; }
}
It does actually run the thread. Note! This is in an Xamarin Android app, and the error only occurs in debug mode. Release works perfectly.
Thread started: #2 Test Thread finished: #2
Here a screenshot from Xamarin:
I tried surrounding the thread creation in a try/catch, but it still throws the null pointer on RunOnNewThread.Start().
However, there must be something else going on. Because it just ran fine 2 times, and the 3rd time I got the null pointer again. Any ideas?
Related
I am using MonoDevelop with GTK Sharp 2.12. I have set this up using the default GTK Sharp windowed project. Add a button, add a button-click event and placed the following code:
protected async void OnBtnTest(object sender, EventArgs e)
{
Debug.WriteLine($"Before: {Thread.CurrentThread.ManagedThreadId}");
await Task.Delay(2000);
Debug.WriteLine($"After: {Thread.CurrentThread.ManagedThreadId}");
using (var msg = new MessageDialog(this, DialogFlags.Modal,
MessageType.Info, ButtonsType.Ok, "CRASH"))
{
msg.Run();
msg.Destroy();
}
}
The output is:
Before: 1
Started Thread 27672
After: 4
(TestSyncContext:26912): Gdk-CRITICAL **: gdk_window_set_geometry_hints: assertion 'GDK_IS_WINDOW (window)' failed
The "critical" line is a crash in the program -- This is because the UI thread didn't return when continuing on to show the MessageDialog. You can see the managed thread ID changed after the call to await.
Puzzled by this, I started researching and found this bit of code from a long, long time ago; Specifically these lines caught my attention:
gtk_init (ref argc, ref argv);
SynchronizationContext.SetSynchronizationContext (new GLib.GLibSynchronizationContext ());
So I started to wonder: Does GTK Sharp not set up a synchronization context by default?
I decided to throw it in the code, but GLib.GLibSynchronizationContext() does not exist in the GLib library.
OK, that's odd -- I searched for that on the web and found the source code to that object; Copied and pasted it in to my project, then called it as so:
class MainClass
{
public static void Main(string[] args)
{
Application.Init();
SynchronizationContext.SetSynchronizationContext(new GLibSynchronizationContext());
MainWindow win = new MainWindow();
win.Show();
Application.Run();
}
}
Ran it again, and it performs how I would have expected it to without adding a context:
Before: 1
Started Thread 22744
After: 1
No crashes. UI thread came back to continue on down the method.
My questions are:
Did GTK Sharp intentionally not include a synchronization context in their UI framework on purpose?
Did GTK Sharp intentionally not attempt to initialize a sync-ctx on purpose? Meaning they never intended it to work with the async/await pattern by default?
Why is GLib.GLibSynchronizationContext no longer available?
Is what I did to fix it the correct way to add a proper sync-ctx to GTK Sharp?
I have production code with this fix going out, and I want to make sure that what I did isn't unorthodox. OR: maybe there is a better way to set up GTK Sharp to handle the async/await pattern that isn't very well documented.
What I want to do:
- synchronously (or even asynchronously) load settings from USB drive before first page loads
What I did:
- in OnLaunched method for App.xaml.cs I invoked this static function:
public static async void LoadSettings(string folderName = "Config", string fileName = "Settings.xml")
{
try
{
StorageFile configFile = null;
// scan through all devices
foreach (var device in await KnownFolders.RemovableDevices.GetFoldersAsync().AsTask().ConfigureAwait(false))
{
// folder that should have configuration
var configFolder = await device.GetFolderAsync(folderName).AsTask().ConfigureAwait(false);
if (configFile != null && configFolder != null && await configFolder.GetFileAsync(fileName).AsTask().ConfigureAwait(false) != null)
{
throw new Exception("More than one configuration file detected. First found configuration file will be used.");
}
else
configFile = await configFolder.GetFileAsync(fileName).AsTask().ConfigureAwait(false);
}
if (configFile == null)
throw new Exception("Configuration file was not found, please insert device with proper configuration path.");
string settingString = await FileIO.ReadTextAsync(configFile).AsTask().ConfigureAwait(false);
XmlSerializer serializer = new XmlSerializer(typeof(Settings));
using (TextReader reader = new StringReader(settingString))
{
AppSettings = (Settings)serializer.Deserialize(reader); // store settings in some static variable
}
}
catch (Exception e)
{
//return await Task.FromResult<string>(e.Message);
}
//return await Task.FromResult<string>(null);
}
As you can see right now it's async void method, so I don't even want to synchronize it in any way with UI thread. It should just fire and do something. With ConfigureAwait(false) I want to be sure that it will never try to return to context. These returns at the end are remnants of other things I tried (I wanted to do this better way, this is the most primitive solution and it still doesn't work).
Anyway, because that's where the fun begins: everything works well when I debug application on local machine with Win 10. And I get deadlocked thread on Win 10 IOT installed on Raspberry Pi 3 (I installed it from the scratch today, last version).
But deadlock is not the weirdest thing. Weirdest thing is when it appears.
Like I said, invocation of this method looks like that:
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
Configuration.Settings.LoadSettings();
After that everything in this method goes normally, so I navigate to my first page somewhere below:
if (e.PrelaunchActivated == false)
{
if (rootFrame.Content == null)
{
rootFrame.Navigate(typeof(LogScreen), e.Arguments);
}
Window.Current.Activate();
}
Everything still works. User needs to write his code, I check if this code is available in settings and after that user can press "OK" to move to next page. Somewhere in LogScreenViewModel this method is responsible for that:
private void GoForward(bool isValid)
{
try
{
_navigationService.NavigateTo("MainPage"); // it's SimpleIoc navigation from MVVMLight
}
catch (Exception e)
{
Debug.WriteLine($"ERROR: {e.Message}");
}
}
And deadlock happens when _navigationService.NavigateTo("MainPage") is reached. Basically right now UI thread freezes. If I wait for long enough I will see catched exception in Output saying that messenger seemed occupied (I can't show the screen because I don't have access to that Raspberry right now) and after some timeout this thread was killed (like 30 seconds or something) - after that UI thread unlocks and application proceeds to MainPage. It doesn't happen on PC - MainPage appears immediately, no exceptions, no deadlocks.
I tried waiting on first page for like 1 minute to check if some deadlock exception would fire on it's own - but it doesn't. It will fire ONLY after I try to proceed to next page.
What else I tried instead of this fire-and-forget approach:
Making OnLaunched async and await LoadSettings returning Task - same thing happens in the same place, and no problem on PC.
Using:
Window.Current.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, async () => await Configuration.Settings.LoadSettings(); ).AsTask().Wait(); If I remember correctly it deadlocked immediately on Wait(), even with ConfigureAwait(false) everywhere, but it also happened on PC.
Allowing LogScreen to load, make it's OnNavigatedTo method async and await LoadSettings - same deadlock in same place
Allowing LogScreen to load and use Dispatcher from there like in point 2. It deadlocked the same way after reaching Wait(), on PC too.
Trying to force LoadSettings to be fully synchronous by replacing every await with AsTask().GetAwaiter().GetResults(). It worked well on PC... and of course deadlock on Raspberry.
What am I missing? What else can I try? Because to be honest right now it looks to me that Win 10 IOT .NET runtime is bugged or something.
I think I resolved the issue. This code was generally speaking not mine and after some digging I noticed that someone before me tried to list some other external devices while navigating to MainPage. It was not really async-safe code (someone probably wasn't aware of synchronization context) and it worked on Win 10 only because on desktop it was looking for COM0 device and I only have COM2, so method causing trouble was not even invoked at all.
I still have no idea how related it was to my configuration (because it somehow was working without it), but after I fixed issues with this old not-async-safe code it started to behave as expected.
Im using System.Windows.Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input, new Action(() => ... for a wpf graphic refresh.
It works in my other function greatfully, but in my SQL delete function it wount be triggered/executed.
I tried it with System.Windows.Forms.Application.DoEvents(); but it wount do anything.
Set_Loading_Changed()
{
System.Windows.Application.Current.Dispatcher.BeginInvoke(
DispatcherPriority.Input,
new Action(() =>
{
if (BLoading)
{
DataGrid_Anzeige.IsEnabled = false;
Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
}
else
{
DataGrid_Anzeige.IsEnabled = true;
Mouse.OverrideCursor = null;
}
}));
}
Btn_Remove()
{
...
Set_Loading_Changed();
using (OleDbConnection ODC = new OleDbConnection("..."))
{
foreach (var selectedRow in DataGrid_Anzeige.SelectedItems.OfType<DataRowView>())
{
sSQL_Statement = "...";
ODC.Open();
OleDbCommand ODCmd = new OleDbCommand(sSQL_Statement, ODC);
ODCmd.ExecuteNonQuery();
ODC.Close();
EDIT:
I insert the complete part of my Set_Load_Changed() function, hope you can get a clue with this informations.
Im using it primarly in my search Thread (Task.Factory.StartNew(() => { ... }));) so it must be the DispatcherPriority.Input.
You're running into a common issue with misunderstanding the WPF threading system. The way WPF is structured is with one thread for the program to run and modify the UI in, usually called the UI thread, and a second thread which you have no normal way of using, which automatically renders the UI, commonly called the rendering or compositing thread.
The key point you need to know here is that if you stall the UI thread with a large operation (like a database read or a large calculation) immediately after BeginInvoke(), then you're preventing the UI thread from running those commands until you allow it to invoke the next action. BeginInvoke() simply queues the action to be performed the next time the dispatcher is allowed - the dispatcher will not interrupt what is currently being done. Setting the priority to Input ensures that it will be handled ahead of other lower priority work, but still will not cause it to interrupt your current method.
If you instead call Invoke(), you are interrupting your work to ask the dispatcher to perform the action and then return to what you're doing when it's finished.
While this is preferable to the behavior you're currently getting, this isn't how you're intended to use the dispatcher, and will still cause your app to appear 'frozen' while it completes the long operation. To avoid this, the easiest thing to do is run the long operation in a Task, using the async/await keywords and the Task Parallel Library.
Stephen Cleary has an excellent blog where he covers a lot of topics related to this. His introductory post (dating back to the keywords' introduction) is here.
I would encourage poking around his blog if you have more issues in this area - he's one of the leading experts in explaining this area, and has covered most of the problems you run into.
Further reading:
What's the difference between Invoke() and BeginInvoke()?
WPF Threading Model
To change the cursor in WPF is unfortunately not as straightforward as in WinForms. I remember struggling with it myself until I stumbled upon the following solution. I didn't come up with this myself, I'll try and find the source to give credit where it is due.
using System;
using System.Collections.Generic;
using System.Windows.Input;
namespace MyNamespace
{
public class OverrideCursor : IDisposable
{
static Stack<Cursor> s_Stack = new Stack<Cursor>();
public OverrideCursor(Cursor changeToCursor = null)
{
if (changeToCursor == null)
changeToCursor = Cursors.Wait;
s_Stack.Push(changeToCursor);
if (Mouse.OverrideCursor != changeToCursor)
Mouse.OverrideCursor = changeToCursor;
}
public void Dispose()
{
s_Stack.Pop();
var cursor = _stack.Count > 0 ? _stack.Peek() : null;
if (Mouse.OverrideCursor != cursor)
Mouse.OverrideCursor = cursor;
}
}
}
Now this disposable class can be used anywhere in your project to change the cursor temporarily.
using (new OverrideCursor())
{
//your code
}
This will change the cursor to anything you want by passing the cursor as parameter of the constructor, or nothing to use Cursors.Wait by default.
For the time needed to execute any code placed inside the using-block the cursor will be changed turning back to normal afterwards.
You can also initiate an object of the class without the using-block to set it indefinitely but you shouldn't forget to call Dispose() when done.
Edit: source: https://stackoverflow.com/a/675686/4579864
If want to do whatever you are doing in Set_Loading_Changed() before you connect to the database, you should call Invoke instead of BeginInvoke:
Set_Loading_Changed()
{
System.Windows.Application.Current.Dispatcher.Invoke(...);
}
What's the difference between Invoke() and BeginInvoke()
I am building a document management system currently and I was trying to change the cursor to a "waiting" cursor while the document is loading, pretty standard.
As per the MSDN documentation, I am using the following code:
System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
try
{
newPage.LoadForm(data);
}
finally
{
System.Windows.Input.Mouse.OverrideCursor = null;
}
The problem is, after LoadForm is finished, the cursor doesn't return to its normal state. I have debugged the program and the "null" line is being run so I have no idea what the problem is.
Any ideas?
If this is a long-running operation, you might consider moving this whole code to a Task (though in that case you'd have to dispatch the changes to the OverrideCursor property back to the main thread).
I tested this quickly with a Sleep simulating a long-running application and it seemed to work fine (I put this code in the window's constructor in an empty WPF application for testing).
Task.Factory.StartNew(() =>
{
Application.Current.Dispatcher.Invoke(() =>
System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait);
try
{
Thread.Sleep(5000);
}
finally
{
Application.Current.Dispatcher.Invoke(() =>
System.Windows.Input.Mouse.OverrideCursor = null);
}
});
WORKAROUND
You must set it to the cursor type you want instead of setting it to null. So, instead of setting it to null, set it to Arrow (I assume that is what you would want in Normal state).
So in finally block replace your code with this:
System.Windows.Input.Mouse.OverrideCursor = System.Windows.Input.Cursors.Arrow;
EDIT 1:
Try setting the Cursor to null at the end of try block if in case you do not want to use the workaround.
I'm writing a debugger extension VSPackage in which I want to execute a statement in the debugged process when a breakpoint is hit. In my extension code I have this:
void Initialize()
{
// ...standard vspackage init code omitted...
Globals.Init((DTE2)GetService(typeof(DTE)));
Globals.DebuggerEvents.OnEnterBreakMode += (dbgEventReason reason, ref dbgExecutionAction action) =>
{
try
{
var e1 = Globals.Application.Debugger.GetExpression("1+2");
Debug.WriteLine(e1.Value); // Prints "3"
Globals.Application.Debugger.ExecuteStatement("x = 1+2", 1000);
Debug.WriteLine("OK"); // Never prints this
}
catch (Exception ex)
{
Debug.WriteLine("Error: "+ex); // Nor this
}
}
}
When debugging this extension in a VS instance I load a trivial program looking like this
static void Main()
{
int x = 5;
Console.WriteLine("X is "+x); // Breakpoint on this line
}
When the breakpoint is hit in the debugged process the handler is called and the output window for the extension shows "3", so evaluating expressions works, but it never succeeds executing the statement. Nothing more is printed to the output window. No exception or timeout occurs and I can't continue debugging the process, the debugger appears to have crashed.
The globals class just holds the DTE and DebuggerEvents
public static class Globals
{
public static void Init(DTE2 dte)
{
Application = dte;
DebuggerEvents = dte.Events.DebuggerEvents;
}
public static DTE2 Application { get; private set; }
public static DebuggerEvents DebuggerEvents { get; private set; }
}
What am I doing wrong, or misunderstanding here?
This is an old question, but there is so little on Google about these issues, I thought I'd offer some help. Some important considerations:
Use GetExpresssion3(TreatAsStatement:=True), if possible, instead of ExecuteStatement (I could not get ExecuteStatement working properly).
The thread calling your delegate (OnEnterBreakMode) is the same thread that will need will to run again in order to execute your expression or statement. Therefore, call your GetExpression method on a new thread (Task.Run..)
You will have to monitor and manage the Reason value for OnEnterBreakMode. The initial Reason is UnwindFromException for the actual unhandled exception. Then, it is expected you are setting a variable, such as tempStack = New System.Diagnostics.StackTrace(True). OnEnterBreakMode will be called again following execution of this statement, but this time with Evaluation for the Reason. At this point you now call all of your GetExpressions to collect all of your data without additional OnEnterBreakMode calls.
Dim dte2 As EnvDTE80.DTE2 = GetGlobalService(GetType(EnvDTE.DTE))
Dim debugger5 as EnvDTE100.Debugger5 = Dte2.Debugger
Interesting design observation: System.Diagnostics.StackTrace is a very strangely designed class in the context of the rest of the .NET framework until you have to work on this project where you are extracting the StackTrace through this very technique and see the benefit of its otherwise odd design.
I was tinkering a lot with Visual Studio debugging, and the ultimate cause of freezing was always related to thread handling: VS allows any piece of code to run while debugging only in the main thread. Every other thread is disabled and in case your debug code depends on a different thread it will freeze too.
My guess: You initialized your DTE in a different thread than what you are debugging.
Assumed result: Delegate method tries to load the context of the initializing thread which is different from the debugged thread, and thus it is bound to get frozen.
Proposed solution: Don't use delegate method. They implicitly refer back to the original execution context. Instead register a regular method, and reinitialize your DTE in that context.