Plinq statement gets deadlocked inside static constructor - c#

I came across this situation where the following plinq statement inside static constructor gets deadlocked:
static void Main(string[] args)
{
new Blah();
}
class Blah
{
static Blah()
{
Enumerable.Range(1, 10000)
.AsParallel()
.Select(n => n * 3)
.ToList();
}
}
It happens only when a constructor is static.
Can someone explain this to me please.
Is it TPL bug? Compiler? Me?

It is generally dangerous to call threading code from a static constructor. In order to ensure that the static constructor executes only once, the CLR executes the static constructor under a lock. If the thread running the static constructor waits on a helper thread, there is a risk that the helper thread is going to need the CLR-internal lock for some reason too, and the program will deadlock.
Here is a simpler code sample that demonstrates the problem:
using System.Threading;
class Blah
{
static void Main() { /* Won’t run because the static constructor deadlocks. */ }
static Blah()
{
Thread thread = new Thread(ThreadBody);
thread.Start();
thread.Join();
}
static void ThreadBody() { }
}
Section 10.5.3.3 "Races and deadlocks" of the ECMA CLI spec guarantees the following:
Type initialization alone shall not create a deadlock unless some code
called from a type initializer (directly or indirectly) explicitly
invokes blocking operations.
So, a type initializer (i.e., a static constructor) will not deadlock, provided that no operation in the static constructor blocks the thread. If the static constructor does block, it risks a deadlock.

While the reason has already been explained as to why you wouldn't want to do threaded work inside a static constructor, I thought I'd add that the "right" way to do this instead would be with a static Lazy<T>. This is also more efficient as the work to generate those resources will be defferred until those resources are actually needed.
class Blah
{
// Supply factory method to generate the numbers, but actual generation will be deferred
private static Lazy<List<int>> MyMagicNumbers = new Lazy<List<int>>(Blah.GenerateMagicNumbers);
public void DoSomethingWithMagicNumbers()
{
// Call to Lazy<T>.Value will synchronize any calling threads until value is initially generated from the factory
List<int> magicNumbers = Blah.MyMagicNumbers.Value;
// ... do something here ...
}
private List<int> GenerateMagicNumbers()
{
return Enumerable.Range(1, 10000)
.AsParallel()
.Select(n => n * 3)
.ToList();
}
}

For what its worth, the issue does not arise on Mono:
[mono] /tmp # dmcs par.cs
[mono] /tmp # mono ./par.exe
Do you have a windows compiled binary so I can compare the generated MSIL? I'm not convinced this is a library-only issue, and I'm curious :)
Comparing the IL was a bit messy, so I decided to just try both binaries on both platforms.
Hehe I revived my old Windows virtual machine just to test this :)
Running the VS compiled binaries on Mono is no problem. You could try it on windows using 2.10.1 (http://www.go-mono.com/mono-downloads/download.html), only 77.4Mb :)
(I used a custom built mono 2.11 on linux so it could be that the feature support is not complete yet)
\ run on platform: MS.Net 4.0 Mono 2.1x
built on: -------------+----------------------------------------
Visual Studio | deadlock no deadlock
|
MonoDevelop | deadlock no deadlock
I also noticed that when running on windows, a CTRL-C is able to break out of the lock.
Will post if I find some more to this.
Update 2
Well, installing Mono runs circles around installing installing VSExpress even on windows. Installing mono has finished in 4 minutes, and resulted in:
C:\Users\Seth>"c:\Program Files (x86)\Mono-2.10.1\bin\mono.exe" ConsoleApplication2.exe
C:\Users\Seth>
No deadlock :) Now all that remains is waiting for VSExpress to be installed (forever) and istall debugging tools (unknown) and than have a crack at it (probably till late night). CU later

Related

Recommended way to prevent a .Net Core 5 console app from ending when run on Linux as a service

I have a .Net Core 5 console app that runs on Linux (Debian 10). The basic structure is something like this:
class Program
{
static async Task Main(string[] args)
{
await SetupStuffAsync();
MonitorGpioService.Run();
RunAScheduledServiceOnATimer();
Console.ReadLine();
}
}
Basically, it runs on an Orange Pi Zero (similar to a Raspberry Pi), waiting for a signal on a GPIO pin. When that signal arrives, it reads the serial port for a few milliseconds, writes the data to a MariaDB database (using EF Core), and posts the data to a Web API. It also runs some scheduled maintenance code every 5 minutes (using System.Timers.Timer()).
This app runs unattended - there's not even a screen - and must run always, from the moment the Orange Pi is booted up until it is shutdown.
Console.ReadLine() worked fine in stopping the app from ending when I was manually running the app during development.
But now I need the app to run automatically when Debian starts up, so I did the following:
sudo nano /etc/systemd/system/orangePi.service
[Unit]
Description=orangePi.service
[Service]
Type=simple
ExecStart=/root/dotnet/dotnet sr/local/bin/orangePiService/orangePiService.dll
Restart=on-failure
RestartSec=10
KillMode=process
[Install]
WantedBy=multi-user.target
This works great - the app starts up automatically on bootup, but there's a problem. Console.ReadLine() is being completely ignored. It literally executes everything and then ends. I suppose this makes sense as it's not running in the console in this case.
I know I can, for example, put an infinite loop at the end to prevent it from ending:
class Program
{
static async Task Main(string[] args)
{
await SetupStuffAsync();
MonitorGpioService.Run();
RunAScheduledServiceOnATimer();
while (0 == 0) {};
}
}
And this works, but I don't like it. Not only is it not pretty, but also I would imagine that it's using up a lot of CPU to run that loop.
I could do this instead:
class Program
{
static async Task Main(string[] args)
{
await SetupStuffAsync();
MonitorGpioService.Run();
RunAScheduledServiceOnATimer();
while (0 == 0)
{
Thread.Sleep(int.MaxValue);
};
}
}
Which I would imagine would be less taxing on the CPU, but I think it's blocking this thread. Is that a problem? I know it depends on what the rest of the code looks like, but it's quite a bit of code to post here. What I can say is that most of the action happens in MonitorGpioService.Run() which I am posting below in an extremely simplified format:
using System.Device.Gpio;
public static class MonitorGpioService()
{
static GpioController _controller;
public static void Run()
{
_controller = new GpioController();
_controller.RegisterCallbackForPinValueChangedEvent((int)Settings.GpioPin.Read, PinEventTypes.Rising, onSignalPinValueChangedEvent);
}
private static void onSignalPinValueChangedEvent(object sender, PinValueChangedEventArgs args)
{
string data = ReadSerialPortFor40ms();
using (var context = new eballContext())
{
await _dbContext.Readings.AddRangeAsync(readings);
await _dbContext.SaveChangesAsync();
}
}
}
I am using awaits wherever possible, which I think wouldn't be affected by the main thread being blocked. I'm not sure about the firing of the event handler when a GPIO pin state changes though. From my testing, it doesn't appear to be affected by blocking the main thread, but I can't be sure...
In summary (and I apologize for the length of this post), I'm trying to figure out what's the best way to prevent a .Net Core console app from quitting when running on Linux as a service. And by best, I mean one that consumes as little CPU as possible, or maybe blocks threads as little as possible (assuming this is even a problem to begin with, which I'm not really sure considering most of my code runs on Timers or uses awaits).
Well, while loop is a beautiful thing but it is enemy of the CPU.
Instead of while, I often use ManualResetEvent class to prevent closing console apps.
Usually it works when i use this code block in Linux containers on Docker.
I don't have the actual code block, I am going to remember it like;
public static ManualResetEvent _Shutdown = new ManualResetEvent(false);
static void Main(string[] args)
{
//Lots of stuff.
_Shutdown.WaitOne();
}
Basically the shutdown signal never comes and console app never closes. Of course you can develop more targeted code to your needs. This prevents console app shutting down while all that stuff works. You can give it a try. Also you can find lots of different apporaches in SO.
From the answers for C# console program wait forever for event
In case of async main method, one could also use await Task.Delay(-1);
Task.Delay() itself is typically more elegant is it allows you to pass a cancellation token, enabling graceful shutdowns if needed.
Thread.Sleep() should also work, but cannot be cancelled. Instead of a while loop you can use Timeout.Infinite to suspend without wasting any cycles

GTK Sharp synchronization context doesn't seem to exist, breaking async/await by default

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.

Library working when called from Console app but not from NUnit test

I'm trying to evaluate a workflow library for a project I'm working on. The lib can be found at github workflow-core.
To start things up I was trying to build a simple workflow, that just writes some text to a file. The curious thing is, that the workflow works fine, when called from a console application project. But when I use the same code in an NUnit test and run it, it doesn't write anything to the file.
I'm a little lost here and don't even know which details are import for you guys to know to help me figure this out, but maybe this might be relevant?
The workflow-core library is build on .NET standard 2.0
The NUnit project and the console project both use .NET Framework 4.7.2
The workflow-core lib uses all kinds of Tasks (as in Task Parallel Library) stuff
The workflow-core lib is build with dependency injection using the Microsoft.Extensions.DependencyInjection library
And here is the relevant code:
First the workflow class:
public class HelloWorldWorkflow : IWorkflow
{
public string Id => nameof(HelloWorldWorkflow);
public int Version => 1;
public void Build(IWorkflowBuilder<object> builder)
{
builder.StartWith((context) =>
{
File.WriteAllText(#"C:\Test\test.txt", "Test line worked!");
return ExecutionResult.Next();
});
}
}
The calling code from the console app (working):
class Program
{
static void Main(string[] args)
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging((config) => config.AddConsole());
serviceCollection.AddWorkflow();
serviceCollection.AddTransient<LogStep>();
var serviceProvider = serviceCollection.BuildServiceProvider();
var host = serviceProvider.GetService<IWorkflowHost>();
host.RegisterWorkflow<HelloWorldWorkflow>();
host.Start();
host.StartWorkflow(nameof(HelloWorldWorkflow));
Console.WriteLine("Done");
Console.ReadLine();
host.Stop();
}
}
And the code from my test project (not working):
[TestFixture]
public class ExplorationTests
{
private ServiceProvider _serviceProvider;
private IWorkflowHost _host;
[OneTimeSetUp]
public void Init()
{
var serviceCollection = new ServiceCollection();
serviceCollection.AddLogging((config) => config.AddConsole());
serviceCollection.AddWorkflow();
serviceCollection.AddTransient<LogStep>();
serviceCollection.AddTransient<HelloWorldWorkflow>();
_serviceProvider = serviceCollection.BuildServiceProvider();
_host = _serviceProvider.GetService<IWorkflowHost>();
_host.RegisterWorkflow<HelloWorldWorkflow>();
_host.Start();
}
[Test]
public void Test()
{
_host.StartWorkflow(nameof(HelloWorldWorkflow));
}
[OneTimeTearDown]
public void TearDown()
{
_host.Stop();
}
}
I'd be glad for any clues on how to figure this out.
Execution of workflows is asynchronous, therefore you have to wait for some kind of event to occur which signals the completion.
Otherwise your test teardown will kill the host before the workflow has the chance to do anything.
This answer's first version contained:
Adding .Wait() or one of its overloadings (which allow to specify a maximum duration to wait) to the result of StartWorkflow to block the test until the workflow has completed.
Unfortunately that's wrong as StartWorkflow returns a Task yielding only the ID of the workflow instance. When this task is resolved your workflow probably hasn't done anything meaningful.
There is a feature request on GitHub asking for the desired feature: Wait for workflow to finish
Until that request is resolved, you may help yourself by creating a ManualResetEvent or maybe AutoResetEvent and putting it somewhere your final workflow step can access and call .Set() on it. Your test should wait for that by calling .WaitOne() on it (this is blocking).
Another event which might be sufficient (but inefficient) is just having waited a long enough duration: Thread.Sleep(2000) waits two seconds. Please be aware that even after that it's possible that your workflow has not completed due to the asynchronous nature of the workflow executor.
Can you try by making 'var serviceCollection' as class member of ExplorationTests. Otherwise code looks ok.
It looks like your test starts a task running in the host and then exits without waiting for completion. The one time teardown would then run immediately and stop the host.
You should not be ending the test without waiting for the task to complete.

Can't execute statement with VS Debugger Interop

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.

Make my COM assembly call asynchronous

I've just "earned" the privilege to maintain a legacy library coded in C# at my current work.
This dll:
Exposes methods for a big legacy system made with Uniface, that has no choice but calling COM objects.
Serves as a link between this legacy system, and another system's API.
Uses WinForm for its UI in some cases.
More visually, as I understand the components :
*[Big legacy system in Uniface]* ==[COM]==> [C# Library] ==[Managed API]==> *[Big EDM Management System]*
The question is: One of the methods in this C# Library takes too long to run and I "should" make it asynchronous!
I'm used to C#, but not to COM at all. I've already done concurrent programming, but COM seems to add a lot of complexity to it and all my trials so far end in either:
A crash with no error message at all
My Dll only partially working (displaying only part of its UI, and then closing), and still not giving me any error at all
I'm out of ideas and resources about how to handle threads within a COM dll, and I would appreciate any hint or help.
So far, the biggest part of the code I've changed to make my method asynchronous :
// my public method called by the external system
public int ComparedSearch(string application, out string errMsg) {
errMsg = "";
try {
Action<string> asyncOp = AsyncComparedSearch;
asyncOp.BeginInvoke(application, null, null);
} catch (ex) {
// ...
}
return 0;
}
private int AsyncComparedSearch(string application) {
// my actual method doing the work, that was the called method before
}
Any hint or useful resource would be appreciated.
Thank you.
UPDATE 1:
Following answers and clues below (especially about the SynchronizationContext, and with the help of this example) I was able to refactor my code and making it to work, but only when called from another Window application in C#, and not through COM.
The legacy system encounters a quite obscure error when I call the function and doesn't give any details about the crash.
UPDATE 2:
Latest updates in my trials: I managed to make the multithreading work when the calls are made from a test project, and not from the Uniface system.
After multiple trials, we tend to think that our legacy system doesn't support well multithreading in its current config. But that's not the point of the question any more :)
Here is a exerpt of the code that seems to work:
string application;
SynchronizationContext context;
// my public method called by the external system
public int ComparedSearch(string application, out string errMsg) {
this.application = application;
context = WindowsFormsSynchronizationContext.Current;
Thread t = new Thread(new ThreadStart(AsyncComparedSearchAndShowDocs));
t.Start();
errMsg = "";
return 0;
}
private void AsyncComparedSearch() {
// ANY WORK THAT AS NOTHING TO DO WITH UI
context.Send(new SendOrPostCallback(
delegate(object state)
{
// METHODS THAT MANAGE UI SOMEHOW
}
), null);
}
We are now considering other solutions than modifying this COM assembly, like encapsulating this library in a Windows Service and creating an interface between the system and the service. It should be more sustainable..
It is hard to tell without knowing more details, but there are few issues here.
You execute the delegate on another thread via BeginInvoke but you don't wait for it. Your try\catch block won't catch anything as it has already passed while the remote call is still being executed. Instead, you should put try\catch block inside AsyncComparedSearch.
As you don't wait for the end of the execution of remote method (EndInvoke or via callback) I am not sure how do you handle the results of the COM call. I guess then that you update the GUI from within AsyncComparedSearch. If so, it is wrong, as it is running on another thread and you should never update GUI from anywhere but the GUI thread - it will most likely result with a crash or other unexpected behavior. Therefore, you need to sync the GUI update work to GUI thread. In WinForms you need to use Control.BeginInvoke (don't confuse it with Delegate.BeginInvoke) or some other way (e.g. SynchronizationContext) to sync the code to GUI thread. I use something similar to this:
private delegate void ExecuteActionHandler(Action action);
public static void ExecuteOnUiThread(this Form form, Action action)
{
if (form.InvokeRequired) { // we are not on UI thread
// Invoke or BeginInvoke, depending on what you need
form.Invoke(new ExecuteActionHandler(ExecuteOnUiThread), action);
}
else { // we are on UI thread so just execute the action
action();
}
}
then I call it like this from any thread:
theForm.ExecuteOnUiThread( () => theForm.SomeMethodWhichUpdatesControls() );
Besides, read this answer for some caveats.

Categories