I wish to develop a debugging service that needs to run constantly in the background, even when I hit a breakpoint -- especially during those moments. Is there any way I could do that, other than having to manually unfreeze the specific thread in the thread window ? I'd like it to be something I don't have to take care of manually. I thought about creating a thread that run inside another appDomain, but I bet that thread will also end up frozen when I hit a breakpoint. I have not tested it though.
I found a solution. I will make a visual studio extension. I did some tests and it's possible to have a thread running in the background all the time within an extension
Here's a simple proof of concept that keeps emiting the result of an evaluation, even when the debugger hits a breakpoint:
private Command1(AsyncPackage package, OleMenuCommandService commandService)
{
Task.Run(() => {
DTE dte = (DTE)ServiceProvider.GetServiceAsync(typeof(DTE)).Result;
while (true)
{
Expression ex2 = dte.Debugger.GetExpression("WinFormsApp1.Test.RunStatic(str);");
Debug.WriteLine("### " + ex2.Value);
Thread.Sleep(1000);
}
}
}
The logic starts when Command1 is initialized, which won't be appropriate for the real thing, but good enough for the POC.
Related
I'm making an Visual Studio adornment extension. I want to update adornments if there is no user input at least 2 seconds. So i constructed a worker and tried to remove and add adornment but VS says it can't be updated because non-ui thread had called it. So I waited without thread then my editor goes really laggy (because the ui thread waits)
I want to know if there is a way to update adornments with lazy update.
Drawing adornment is done by calling AddAdornment(), and i can't find how to invoke ui thread to draw.
Below is my code
internal async void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
{
Print("OnLayoutChanged Called");
task = Task.Factory.StartNew(() =>
{
Print("task Started");
if (e.NewSnapshot != e.OldSnapshot)
{
parseStopwatch.Restart();
shouldParse = true;
}
ParseWork(e);
});
await task;
}
private async void ParseWork(object param)
{
var e = (TextViewLayoutChangedEventArgs)param;
if (e == null)
{
shouldParse = false;
parseStopwatch.Stop();
CsharpRegionParser.ParseCs(this.view.TextSnapshot);
DrawRegionBox();
return;
}
while (shouldParse)
{
Task.Delay(10);
if ((shouldParse && parseStopwatch.ElapsedMilliseconds > 2000) || parseStopwatch.ElapsedMilliseconds > 5000)
{
break;
}
}
shouldParse = false;
parseStopwatch.Stop();
CsharpRegionParser.ParseCs(this.view.TextSnapshot);
DrawRequest(e);
return;
}
I'm not sure why you were down-voted, particularly because this is an interesting problem when dealing with extensions.
So, to your first problem: Visual Studio has the same requirements as WPF (with some added complications due to its COM dependency). You can't update a UI element when you're not on the Main (UI) thread. Unfortunately, if you dive right in and approach it using the strategies you'd use for WPF, you'll experience a whole other world of problems (deadlocks, mostly).
First things first, brush up on how to handle switching from background to UI threads in Visual Studio extension land. I found Asynchronous and Multithreaded programming within VS using JoinableTaskFactory to be helpful in explaining.
I had to do something similar with an expensive parsing operation. It was pretty straight forward.
My parser executes as part of an IViewModelTagger instance and uses the following sequence (roughly):
It subscribes to the ITextBuffer.ChangedLowPriority event with an async void event handler.
Immediately on fire, it cancels any parsing operation in progress via a CancellationToken.Cancel() call. The cancellation token is passed into everything that supports it (in Roslyn, it's supported everywhere you would want it to be).
It begins the parsing operation, but before starting it, I have a Task.Delay(200, m_cancellationToken) call. I 200ms based on my typing speed and the fact that Roslyn's operations have CancellationToken overloads for anything expensive (my parsing work is pretty light-weight, too). YMMV.
I work with WPF components that require the UI thread quite a bit and they're intermingled within the IViewModelTagger and the IWpfTextViewListener. They're lightweight enough that I could have skipped async'ing them, but on very large classes they can hang the UI.
To handle this, I did the following:
On the TextViewLayoutChanged, I subscribe with an async void event handler.
I Task.Run() the expensive operations first, preventing the UI from being blocked.
When I do the final creation of the WPF UI elements and add them as adornments finalization (along with a couple of operations within the SDK that require it), I await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync() to get the UI thread.
I mentioned "other SDK operations", that's important. There are several things you cannot do within the SDK on anything but the Main thread (memory is failing me now, but parts of the TextView in particular will fail, and not consistently, if they're accessed on background threads).
There are more options for executing the work off of the UI thread (Ordinary Task.Run works, as well as ThreadHelper.JoinableTaskFactory.Run). The Andrew Arnott post linked earlier in my answer explains all of the choices. You'll want to understand that fully since there are reasons to use some over others depending on the task.
Hope that helps!
Task.Delay as used in your code returns a task that completes when you delay. If you call it like that and ignore the result, it didn't do what you thought it did. What you probably meant to is instead of calling Task.Factory.StartNew as you did, you want:
var cancellationTokenSource = new CancellationTokenSource();
Task.Delay(2000, cancellationTokenSource.Token).ContinueWith(() => DoWork(), cancellationTokenSource.Token, TaskScheduler.Current).
This says effectively "kick off a timer that'll wait 2 seconds, and then once it completes run the DoWork method on the UI thread. If more typing happens, then you can call cancellationTokenSource.Cancel() and just run again.
Also, I do have to ask about your type "CSharpRegionParser". If you need region information and you're on Visual Studio 2015, then you can get the syntax tree from Roslyn and you should be watching workspace change events rather than hooking LayoutChanged. You're also best off then structuring your system as a tagger/adornment manager pair as it might be clearer to write...it's not clear to me why you'd do parsing logic in LayoutChanged since LayoutChanged is something that happens during visual layout, including scrolling, resizing, etc.
I have a project in Xamarin.IOS which interacts with a UI component via NSEvents. UI sends messages through events with a payload - google's protobuf encoded objects. UI is written in ObjC, the logic is written in C#.
Each NSEvent is caught in an observer that invokes internal logic which begins the processing of a message. These messages are put into a queue and eventually taken by threads from the queue.
When a message arrives, the program can create a thread for it, and that's the place where it fails. The code is legacy, so we are using Thread. I write
Thread t = new Thread(ThreadProc);
t.IsBackground = true;
t.Start();
The code used to work a short while ago, also it works sometimes. Sometimes the thread is simply not created. No error is reported.
If I create a thread not in a context of an observer, the thread is started.
I have no idea why it may happen. The problem arises in the very initialization of the application, when the first thread is about to be created. So I don't think there are too many threads.
I have tried to re-create it with Task interface. Tasks are created and started alright, but I can not migrate entire solution to Tasks, unfortunately.
I guess there is some configuration issue or like that since it used to work. I just don't get what it might be. What can affect Thread.Start()?
UPD: I've rolled back to a very old commit which used to work, now it fails too. So it seems not to be a configuration issue, but ios/xamarin issue.
I've never seen anything remotely similar (creating and starting a Thread not actually doing anything), so my first thought is to ensure that this code is actually executed in the first place.
Can you add a Console.WriteLine statements like this:
Console.WriteLine ("creating thread");
Thread t = new Thread(() =>
{
Console.WriteLine ("executing ThreadProc");
try {
ThreadProc ();
} finally {
Console.WriteLine ("finished executing ThreadProc");
}
});
t.IsBackground = true;
t.Start();
Console.WriteLine ("started thread");
and then see what actually shows up in the application output?
I am trying to implement a method called ReadAllLinesAsync using the async feature. I have produced the following code:
private static async Task<IEnumerable<string>> FileReadAllLinesAsync(string path)
{
using (var reader = new StreamReader(path))
{
while ((await reader.ReadLineAsync()) != null)
{
}
}
return null;
}
private static void Main()
{
Button buttonLoad = new Button { Text = "Load File" };
buttonLoad.Click += async delegate
{
await FileReadAllLinesAsync("test.txt"); //100mb file!
MessageBox.Show("Complete!");
};
Form mainForm = new Form();
mainForm.Controls.Add(buttonLoad);
Application.Run(mainForm);
}
I expect the listed code to run asynchronously and as a matter of fact, it does! But only when I run the code without the Visual Studio Debugger.
When I run the code with the Visual Studio Debugger attached, the code runs synchronously, blocking the main thread causing the UI to hang.
I have attempted and succeeded to reproduce the problem on three machines. Each test was conducted on a 64bit machine (either Windows 8 or Windows 7) using Visual Studio 2012.
I would like to know why this problem is occuring and how to solve it (as running without the debugger will likely hinder development).
The problem is that you are calling await reader.ReadLineAsync() in a tight loop that does nothing - except return execution to the UI thread after each await before starting all over again. Your UI thread is free to process windows events ONLY while ReadLineAsync() tries to read a line.
To fix this, you can change the call to await reader.ReadLineAsync().ConfigureAwait(false).
await waits for the completion of an asynchronous call and returns execution to the Syncrhonization context that called await in the first place. In a desktop application, this is the UI thread. This is a good thing because it allows you to update the UI directly but can cause blocking if you process the results of the asynchronous call right after the await.
You can change this behavior by specifying ConfigureAwait(false) in which case execution continues in a different thread, not the original Synchronization context.
Your original code would block even if it wasn't just a tight loop, as any code in the loop that processed the data would still execute in the UI thread. To process the data asynchronously without adding ConfigureAwait, you should process the data in a taks created using eg. Task.Factory.StartNew and await that task.
The following code will not block because processing is done in a different thread, allowing the UI thread to process events:
while ((line= await reader.ReadLineAsync()) != null)
{
await Task.Factory.StartNew(ln =>
{
var lower = (ln as string).ToLowerInvariant();
Console.WriteLine(lower);
},line);
}
I'm seeing the same problem as you to an extent - but only to an extent. For me, the UI is very jerky in the debugger, and occasionally jerky not in the debugger. (My file consists of lots of lines of 10 characters, by the way - the shape of the data will change behaviour here.) Often in the debugger it's good to start with, then bad for a long time, then it sometimes recovers.
I suspect the problem may simply be that your disk is too fast and your lines are too short. I know that sounds crazy, so let me explain...
When you use an await expression, that will only go through the "attach a continuation" path if it needs to. If the results are present already, the code just extracts the value and continues in the same thread.
That means, if ReadLineAsync always returns a task which is completed by the time it returns, you'll effectively see synchronous behaviour. It's entirely possible that ReadLineAsync looks at what data it's already got buffered, and tries to synchronously find a line within it to start with. The operating system may well then read more data from the disk so that it's ready for your application to use... which means that the UI thread never gets a chance to pump its normal messages, so the UI freezes.
I had expected that running the same code over a network would "fix" the problem, but it didn't seem to. (It changes exactly how the jerkiness is shown, mind you.) However, using:
await Task.Delay(1);
Does unfreeze the UI. (Task.Yield doesn't though, which again confuses me a lot. I suspect that may be a matter of prioritization between the continuation and other UI events.)
Now as for why you're only seeing this in the debugger - that still confuses me. Perhaps it's something to do with how interrupts are processed in the debugger, changing the timing subtly.
These are only guesses, but they're at least somewhat educated ones.
EDIT: Okay, I've worked out a way to indicate that it's at least partly to do with that. Change your method like this:
private static async Task<IEnumerable<string>>
FileReadAllLinesAsync(string path, Label label)
{
int completeCount = 0;
int incompleteCount = 0;
using (var reader = new StreamReader(path))
{
while (true)
{
var task = reader.ReadLineAsync();
if (task.IsCompleted)
{
completeCount++;
}
else
{
incompleteCount++;
}
if (await task == null)
{
break;
}
label.Text = string.Format("{0} / {1}",
completeCount,
incompleteCount);
}
}
return null;
}
... and create and add a suitable label to the UI. On my machine, both in debug and non-debug, I see far more "complete" hits than "incomplete" - oddly enough, the ratio of complete to incomplete is 84:1 consistently, both under the debugger and not. So it's only after reading about one in 85 lines that the UI can get a chance to update. You should try the same on your machine.
As another test, I added a counter incrementing in the label.Paint event - in the debugger it only executed 1/10th as many times as not in the debugger, for the same number of lines.
Visual Studio isn't actually executing the asynchronous callback synchronously. However, your code is structured in such a manner that it is "flooding" the UI thread with messages that you may not need to execute on a UI thread. Specifically, when FileReadAllLinesAsync resumes execution in the body of the while loop, it does so on the SynchronizationContext that was captured on the await line in the same method. What this means is for every line in your file, a message is posted back to the UI thread to execute 1 copy of the body of that while loop.
You can resolve this issue by using ConfigureAwait(false) carefully.
In FileReadAllLinesAsync, the body of the while loop is not sensitive to which thread it runs on, so you can use the following instead:
while ((await reader.ReadLineAsync().ConfigureAwait(false)) != null)
In Main, suppose you do want the MessageBox.Show line to execute on the UI thread (perhaps you also have a buttonLoad.Enabled = true statement there). You can (and will!) still get this behavior without any changes to Main, since you did not use ConfigureAwait(false) there.
I suspect the delays you observe in the debugger are due to .NET's slower performance in managed/unmanaged code while a debugger is attached, so dispatching each of those millions of messages to the UI thread is up to 100x slower when you have the debugger attached. Rather than try to speed up that dispatching by disabling features, I suspect item #1 above will resolve the bulk of your problems immediately.
From Task-based Asynchronous Pattern in Microsoft Download Center :
For performance reasons, if a task has already completed by the time
the task is awaited, control will not be yielded, and the function
will instead continue executing.
And
In some cases, the amount of work required to complete the operation
is less than the amount of work it would take to launch the operation
asynchronously (e.g. reading from a stream where the read can be
satisfied by data already buffered in memory). In such cases, the
operation may complete synchronously, returning a Task that has
already been completed.
So my last answer was incorrect (short-timing asynchronous operation is synchronous for performance reasons).
I get an very strange behaviour when I change my Visual Studio 2010 config from Debug to Release:
I have a BackgroundWorker: _bg, in the DoWork I have:
iswaiting = true;
_bg.ReportProgress(1, filePath);
while (iswaiting)
{
;
}
//My other part of code (EDIT: something do to with the `result` I get from the user.)
in the ProgressChanged I have a MessageBox and after the user interaction, iswaiting will be set back to false and the _bg DoWork program will continue.
void _bg_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//my other part of code........
result = Microsoft.Windows.Controls.MessageBox.Show("Question" ,"Title", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);
iswaiting=false;
log(iswaiting.toString());
}
All of these works very well when I run it from Visual Studio or build in Debug mode, but when I build it to Release, I never get out of the while(iswaiting) loop, although I can see from the log iswaiting is already set back to false.
EDIT:
Better way of doing this is more than welcome!!
This is likely due to threading optimizations. In order to safely "see" the change in iswaiting in release mode, you need a memory barrier in place.
The simplest way to "fix" this would be to mark iswaiting as volatile:
volatile bool iswaiting;
That being said, "spinning" like this will completely consume one CPU core. A much better approach would be to use a ManualResetEvent to signal that you can continue.
// Add:
private ManualResetEvent allowProgress = new ManualResetEvent(false);
Then, instead of using iswaiting, you'd do:
_bg.ReportProgress(1, filePath);
allowProgress.WaitOne(); // This will block until it's set
To allow this to continue, use:
result = Microsoft.Windows.Controls.MessageBox.Show("Question" ,"Title", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning);
allowProgress.Set();
The advantage here is that you won't consume CPU while you're blocked, and you don't have to worry about the memory barriers yourself.
So your problem is likely that you are using a boolean field, and you haven't marked it as volatile. Because of this, certain optimizations (often only applied in release mode) can result in both threads accessing a copy of the field that is local to their thread (possibly on the cache of their core of the processor, for example).
However, marking the field volatile isn't really a good idea here. You have a more fundamental problem in that you're performing a spinwait, which is virtually always a bad idea. You should use a method that actually pauses the thread until it is supposed to continue. One way would be to use a ManualResetEvent or a Semaphore.
Looking at your code, what you're waiting on is for the user to dismiss a message box fired in the progress changed event. I would say that, rather than having this in the progress changed event, you should simply include it in the actual "do work" event. It is desirable for the doWork method to not care about the progress changed event once it's fired.
A much better approach would be to use a Semaphore signal that you can continue.
private Semaphore semaphore = new Semaphore(1, 1000);
semaphore.WaitOne();
and after you want to release
semaphore.Release();
I have a WPF application which uses some library code for authentication which needs to run in a Single-Thread Apartment thread. My approach is to spawn a separate thread to get the authentication object, block until the thread returns and then continue execution. However, in some instances my application hangs on Thread.Join(), even though the thread method has returned.
public static ClaimsAuthenticationResult GetClientContextAndCookieCollection(string siteUrl, out CookieCollection cookieResult)
{
ClaimsAuthenticationResult authResult = new ClaimsAuthenticationResult();
// Authentication module needs to run in single-thread apartment state because it uses
// COM library calls where this is required
Thread authenticationThread = new Thread(new ThreadStart(threadMethod));
authenticationThread.SetApartmentState(ApartmentState.STA);
authenticationThread.Start();
// Block until thread completion
authenticationThread.Join(); // Application hangs here
return authResult;
}
private static void threadMethod() {
// In proper application: set result. But for debugging, return immediately
return;
}
I am new to both mulththreading and WPF, so I might be doing something stupid. Does anyone see what's going on here? For the record, I don't get the problem if I don't set the thread to STA, but this is a requirement.
[Edit: It appears that the error only occurs when I call the specified method through a validation binding in a WPF view, specifically on a TextBox. When I call the same code in the constructor of the view, the code runs as expected. This would be a viable workaround, but it would be interesting to know what's actually going on here.]
[Edit: The code here has been simplified a bit for debugging - in the production code, the thread method is inside an AuthThreadWorker object which enables returning the result of the authentication process to the authResult object. But these details are as far as I can tell unrelated to the freeze, as the freeze occurs even in the simplified code.]
Based on your code; it looks as if you're doing it correctly, but the thread is never REALLY terminating. Try setting a breakpoint at the END of the function in the thread; instead of the return keyword (in case you're doing some kind of processing in your return statement that prevents the thread from exiting), as shown in the picture below
. Naming the thread using authenticationThread.Name (or mthread.Name as shown in example) can also aid with debugging. If the thread REALLY terminated, you should see "The thread 'yourname' (0x143c) has exited with code 0 (0x0)." in the Output window of Visual Studio.