EDIT2-->
Take a look at the bottom;
<--EDIT2
I encountered wierd (to me, at least) behaviour.
I even created simple WinForms class and simple class (code below) to test it.
I always thought that calling lock(m_lock) if previous lock(m_lock) call didn't ended, the first one will wait and enter onece the second leaves the scope of lock. Nope.
Flow of actions is:
Create Class1 object;
Call Start() method;
Call DoSomething() method while m_lock is locked in run method;
Output is:
start()
Trying to acquire lock
Acquired lock
Released lock
Trying to acquire lock
Acquired lock
DoSomething() Trying to acquire lock
... hangs ...
What am I missing or doing wrong? I'm a new one to C# (came from C++) so maybe there are some gotchas in C#.
And it still hangs... (by the time I ended writing this post)
EDIT-->
In a real world I use lock to secure read/write/configure on serialPort (with synchroneous read/writes, not async ones). And I see in dbg that there are some internal WaitOne calls. Don't know if it is relevant.
<--EDIT
Here's example:
using System;
namespace LockTester
{
public class Class1
{
object m_lock = null;
bool m_isRunning;
System.Threading.Thread m_thread = null;
public Class1()
{
Console.WriteLine("Class1 ctor");
m_lock = new object();
m_isRunning = false;
}
public void DoSomething(){
Console.WriteLine("DoSomething() Trying to acquire lock");
lock(m_lock){
Console.WriteLine("DoSomething() Acquired lock");
}
Console.WriteLine("DoSomething() Released lock");
}
public void Start(){
Console.WriteLine("start()");
m_isRunning = true;
if (m_thread == null){
m_thread = new System.Threading.Thread(Run);
}
m_thread.Start();
}
public void Stop(){
Console.WriteLine("stop()");
m_isRunning = false;
}
private void Run(){
while (m_isRunning){
Console.WriteLine("Trying to acquire lock");
lock(m_lock){
Console.WriteLine("Acquired lock");
System.Threading.Thread.Sleep(1000);
}
Console.WriteLine("Released lock");
System.Threading.Thread.Sleep(1000);
}
}
}
}
EDIT2:
Ok, found the answer. It was in one more common denominator.
I have found somewhere (SO probably) a solution to redirect Console output to TextBox (for purely testing reasons, you know - small testing applications with gui, which can capture tested object's internal messages being printed to Console).
Here's the code:
used in my form's constructor with :
_writer = new TextBoxStreamWriter(textBox1, this);
Console.SetOut(_writer);
public class TextBoxStreamWriter : TextWriter
{
TextBox _output = null;
Form _form = null;
object _lock = new object();
delegate void SetTextCallback(string text);
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (_output.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
_form.Invoke(d, new object[] { text });
}
else
{
_output.AppendText(text);
}
}
public TextBoxStreamWriter(TextBox output, Form form)
{
_output = output;
_form = form;
}
public override void Write(char value)
{
lock (_lock)
{
base.Write(value);
SetText(value.ToString());
}
}
public override Encoding Encoding
{
get { return System.Text.Encoding.UTF8; }
}
}
Anyone can explain me why this caused this problem?
When you call Form.Invoke, it will do this:
Executes the specified delegate on the thread that owns the control's underlying window handle.
The way it does this is to post a message into the message queue of the owning thread, and wait for that thread to process the message.
As such, Invoke is a blocking call that does not return until the invoked delegate has been called.
Now, the likely reason your code is blocking is that your main GUI thread is already waiting for something else to happen, likely that your external program has completed.
As such it is not actually processing messages.
If this is the reason, then the solution here is to remove the blocking part of the GUI thread. Don't sit around waiting for the external program to complete, instead spin out a task that waits for it to complete and then raises appropriate events on the main form when it does. In the mean time, the main thread is free to process messages, update textboxes, etc.
Note that this means that if starting the external program is done in response to an event, like a button click, you may need to disable parts of the user interface while the program is running, to avoid having the user click the button twice, starting two parallel executions that will both report to the same textbox.
Conclusion: Multithreaded programming is hard!
Related
I try to log text messages from a Task or Thread to a textbox on my form. For that i use Invoke and InvokeRequired methods to syncronize with the main thread, as i can be found in many examples on the internet. See LogMessage_Delegate and LogMessage_Threadsafe below. When i close the app, a boolean flag finished is set to true and the task/thread should stop the work.
This all works fine until i set a breakpoint on the first line of the Form1_FormClosing event handler (finished = true;). Then i see only the console message "LogMessage InvokeRequired", but no corresponding "LogMessage" and the app is hanging.
If i comment out the LogMessage_Threadsafe call in Work (only console messages), then it works again. The app is closing, as expected.
So, can anybody explain this behavior to me? I can find no reason for it.
Please note, i do the flagging in the Form1_FormClosing event handler, so the form is still alive and working.
namespace MultiThreadedTest
{
public partial class Form1 : Form
{
//************************************************************
// Fields
Thread worker = null;
Task task = null;
bool finished = false;
//************************************************************
// Constructor
public Form1()
{
InitializeComponent();
worker = new Thread(Work);
worker.Start();
//task = Task.Factory.StartNew(Work);
}
//************************************************************
// Helper methods
public void LogMessage(string sMessage)
{
LogTextBox.Text += sMessage + Environment.NewLine;
}
/// <summary>
/// Threadsafe wrapper for LogMessage
/// </summary>
delegate void LogMessage_Delegate(string sMessage);
public void LogMessage_Threadsafe(string sMessage)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (this.InvokeRequired)
{
Console.WriteLine("LogMessage InvokeRequired");
LogMessage_Delegate callback = new LogMessage_Delegate(LogMessage_Threadsafe);
this.Invoke(callback, new object[] { sMessage });
}
else
{
Console.WriteLine("LogMessage");
LogMessage(sMessage);
}
}
//************************************************************
// Commands
void Work()
{
while (!finished)
{
Console.WriteLine("Tread/Task Waiting...");
LogMessage_Threadsafe("Tread/Task Waiting...");
Thread.Sleep(1000); // Wait a little...
}
Console.WriteLine("Thread/Task Done");
}
//************************************************************
// Events
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
finished = true;
if (worker != null) worker.Join();
if (task != null) Task.WaitAll(task);
Console.WriteLine("App Done");
}
}
}
You don't need to use raw threads since .NET 4 with the introduction of Tasks. Invoke wasn't needed either but became obsolete since .NET 4.5 with the introduction of async/await. 4.5 also introduced thread-safe progress reporting and cancellation with the IProgress< T> inteface and Progress< T> implementation, as explained in Async in 4.5: Enabling Progress and Cancellation in Async APIs.
Progress<T> calls its delegate on the thread it was created on, in this case the UI thread. You can pass the interface to any background method (task, thread method etc) and use it to report progress.
Given that the earliest supported .NET version is 4.5.2, you can assume these classes will always be available. BTW, TLS 1.2 support was added in 4.5.2 so any holdouts are forced to upgrade already, as they find they can't connect to GMail or other services that demand TLS 1.2.
Your code can be simplified a lot by using these classes. A quick&dirty form with a background timer and thread-safe reporting is the following:
public partial class Form1 : Form
{
System.Threading.Timer _timer;
IProgress<string> _progress;
public Form1()
{
InitializeComponent();
_progress = new Progress<string>(msg => textBox1.Text += msg + "\r\n");
_timer = new System.Threading.Timer(theCallback);
}
private async void theCallback(object state)
{
for (int i = 0; i < 5; i++)
{
await Task.Delay(100);
_progress.Report($"Boo {i}");
}
}
private void Form1_Load(object sender, EventArgs e)
{
_timer.Change(0, 10000);
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
_timer.Dispose();
_timer = null;
_progress = null;
}
}
UPDATE
As for why the original code blocks, it's because Thread.Join() is called from the UI thread in Form.Closing. If the background thread tries to call Invoke to marshal a call to the UI thread, it will get blocked itself precisely because the UI thread is blocked.
This can be avoided by calling BeginInvoke instead of Invoke(). This was the typical way to handle callbacks into the UI thread before .NET 4.
The blocking behaviour can be seen in the Parallel Stacks debugger window (Debug / Windows / Parallel Stacks). When the form deadlocks, two stacks appear, one in the Form.Closing method and one in the LogMessage_Threadsafe method
If you're paused at a breakpoint in the UI thread, calls marshaled to the UI thread via Invoke won't execute, because they run on the UI thread, which is paused.
But judging from your comment, that doesn't seem to be the issue. So I would guess the problem is that, by pausing at that breakpoint, you've allowed the background thread to get into a state where it's blocking on Invoke(), and then you're trying to join that background thread, which will block until the Invoke completes, which will never happen.
As a separate issue, if you're accessing finished from multiple threads, you need to surround the reads and writes with lock blocks to ensure thread safety.
UpDate1:
More detail: Thread 1 and 2 must be continuously active. Thread 1 is updating its GUI and doing HTTP POSTs. Thread 2 is using HTTPListener for incoming HTTP POSTs, and supplying that data to Thread 1. So the GUI needs to be display with current Textbox values and updated when Thread 2 supplies the data. Will Servy's or another approach allow both Threads to do their work concurrently? It appears the main thread waits for Thread 2 to complete it's work. It then takes the prepWork and does work with it. I coded in Servy's example but I couldn't find a definition for Run() with the Task class. It's library has no such method. I'm using Net 4.0 on VS 2010. Is there an equivalent method to use? Start() didn't compile either and I understand you can only run the Task once. Thanks for any additional assistance you can share.
Original Question:
I've tested code that will successfully kick off my event and update my GUI textbox in an event handler if the event is kicked off in what I understand as the UI Thread 1. When I attempt to call a Thread 1 method Fire() from my independent Thread 2 method PrepareDisplay(), Fire() is called and in turns fires off the event. I put in some Thread-safe call code (modeled from MSDN tutorial on Thread-Safety in WinForms), but the event handler still doesn't update the Textbox. When stepping thru the code, it appears that the InvokeRequired is false. My eventual goal is to pass data from Thread 2 to UI Thread 1 and update the Textboxes with the new data. I don't understand why the Thread-safe code isn't enabling this. Can someone help me understand this better, and what I have neglected? Below is the code:
Thank you very much,
namespace TstTxtBoxUpdate
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Aag_PrepDisplay aag_Prep1 = new Aag_PrepDisplay();
Thread AagPrepDisplayThread = new Thread(new ThreadStart(aag_Prep1.PrepareDisplay));
AagPrepDisplayThread.Start();
while(!AagPrepDisplayThread.IsAlive)
;
Thread.Sleep(1000);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new SetOperation());
}
}
}
namespace TstTxtBoxUpdate
{
// Thread 1: UI
public partial class SetOperation : Form
{
private string text;
public event Action<object> OnChDet;
delegate void SetTextCallback(string text);
private Thread demoThread = null;
public SetOperation()
{
InitializeComponent();
OnChDet += chDetDisplayHandler;
}
public void FireEvent(Aag_PrepDisplay aagPrep)
{
OnChDet(mName);
}
private void chDetDisplayHandler(object name)
{
this.demoThread = new Thread(new ThreadStart(this.ThreadProcSafe));
this.demoThread.Start();
}
private void ThreadProcSafe()
{
this.SetText("402.5");
}
private void SetText(string text)
{
if(this.actFreqChan1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.actFreqChan1.Text = text;
}
}
}
}
namespace TstTxtBoxUpdate
{
// Thread 2: Data prepare
public class Aag_PrepDisplay
{
#region Fields
private Aag_PrepDisplay mAagPrep;
#endregion Fields
#region Properties
public Aag_PrepDisplay AagPrepDisp;
public Aag_PrepDisplay AagPrep
{
get { return mAagPrep; }
set { mAagPrep = value; }
}
#endregion Properties
#region Methods
public void PrepareDisplay()
{
mAagPrep = new Aag_PrepDisplay();
SetOperation setOp1 = new SetOperation();
setOp1.FireEvent(mAagPrep); // calls Thread 1 method that will fire the event
}
#endregion Methods
}
}
You're getting to the point of calling InvokeRequired when your main thread is still on Thread.Sleep. It hasn't even gotten to the point of creating a message loop yet (which is one in Application.Run) so there is no message loop for Invoke to marshal a call to.
There are all sorts of issues here. You're creating multiple instance of your form, one that you show, and an entirely different form that you're setting the text of. You clearly did not intend to do this; you want to have a single form that you're setting the text for.
Your main thread should not be doing a busywait until your first thread finishes. It likely shouldn't be there at all. If it weren't for the fact that your new thread is creating yet another new thread, the fact that your main thread is blocking until the second thread finishes and the second thread is trying to marshall a call to the main thread, it would normally deadlock. You shouldn't really be creating a second new thread here at all, but this is a case of two bugs "cancelling each other out". It prevents the deadlock, but both are still incorrect, and inhibit your ability to get to a working solution.
You also shouldn't have the Thread.Sleep in the main thread at all. I have no idea what purpose that's trying to achieve.
If you're goal is simply to start some long running work before showing the first form and then to update that form when you have your results, you're doing way more work than you need to do.
To do this we can have our form accept a Task in its constructor representing the completion of the long running work. It can add a continuation to that task to set a label, or a textbox, or do...whatever, with the results of that Task.
public class SetOperation : Form
{
private Label label;
public SetOperation(Task<string> prepWork)
{
prepWork.ContinueWith(t =>
{
label.Text = t.Result;
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}
Then the main thread simply needs to start a new Task to do the given work in a thread pool thread and pass that in to our form:
[STAThread]
static void Main()
{
Task<string> prepWork = Task.Run(() => DoWork());
Application.Run(new SetOperation(prepWork));
}
private static string DoWork()
{
Thread.Sleep(1000);//placeholder for real work
return "hi";
}
And we're done. Note that DoWork should probably be in its own class designed for handling your business logic; it probably shouldn't be stuck into the Program class.
I have a method (let's call it "CheckAll") that is called from multiple areas of my program, and can therefore be called for a 2nd time before the 1st time has completed.
To get around this I have implemented a "lock" that (if I understand it correctly), halts the 2nd thread until the 1st thread has completed.
However what I really want is for this 2nd call to return to the calling method immediately (rather than halt the thread), and to schedule CheckAll to be run again once it has completed the 1st time.
I could setup a timer to do this but that seems cumbersome and difficult. Is there a better way?
Easy/cheap implementation.
private Thread checkThread = null;
private int requests = 0;
void CheckAll()
{
lock(SyncRoot){
if (checkThread != null; && checkThread.ThreadState == ThreadState.Running)
{
requests++;
return;
}else
{
CheckAllImpl();
}
}
}
void CheckAppImpl()
{
// start a new thread and run the following code in it.
checkThread = new Thread(newThreadStart( () => {
while (true)
{
// 1. Do what ever checkall need to do.
// 2.
lock (SyncRoot)
{
requests--;
if (!(requests > 0))
break;
}
}});
checkThread.Start();
}
Just on a side note, this can have some race conditions. Better implementation swould be to use ConcurrentQueue introduced in .NET 4 which handles all the threading craziness for you.
UPDATE: Here's a more 'cool' implementation using ConcurrentQueue (turns out we don't need TPL.)
public class CheckAllService
{
// Make sure you don't create multiple
// instances of this class. Make it a singleton.
// Holds all the pending requests
private ConcurrentQueue<object> requests = new ConcurrentQueue<object>();
private object syncLock = new object();
private Thread checkAllThread;
/// <summary>
/// Requests to Check All. This request is async,
/// and will be serviced when all pending requests
/// are serviced (if any).
/// </summary>
public void RequestCheckAll()
{
requests.Enqueue("Process this Scotty...");
lock (syncLock)
{ // Lock is to make sure we don't create multiple threads.
if (checkAllThread == null ||
checkAllThread.ThreadState != ThreadState.Running)
{
checkAllThread = new Thread(new ThreadStart(ListenAndProcessRequests));
checkAllThread.Start();
}
}
}
private void ListenAndProcessRequests()
{
while (requests.Count != 0)
{
object thisRequestData;
requests.TryDequeue(out thisRequestData);
try
{
CheckAllImpl();
}
catch (Exception ex)
{
// TODO: Log error ?
// Can't afford to fail.
// Failing the thread will cause all
// waiting requests to delay until another
// request come in.
}
}
}
protected void CheckAllImpl()
{
throw new NotImplementedException("Check all is not gonna write it-self...");
// TODO: Check All
}
}
NOTE: I use a real Thread instead of a TPL Task because a Task doesn't hold on to a real thread as an optimization. When there's no Thread, that means at the time your application closes, any waiting CheckAll requests are ignored.(I got bitten hard by this when I thought I'm so smart to call my logging methods in a task once, which ignored a couple of dozen log records when closing. CLR checks and waits for any waiting threads when gracefully exiting.)
Happy Coding...
Use a separate thread to call CheckAll() in a loop that also waits on a semaphore. A 'PerformCheck()' method signals the semaphore.
Your system can then make as many calls to 'PerformCheck()' as it might wish, from any thread, and CheckAll() will be run exactly as many times as there are PerformCheck() calls, but with no blocking on PerformCheck().
No flags, no limits, no locking, no polling.
You can setup a flag for this.
When this CheckAll() method runs. at the end of this method you can put a flag for each of the separate method. means if the method is being called from other method lets say a() then immidiately after this it is going to be called from b() then>>> when it is called from a() put a flaga variable(which may be global) in CheckAll() at the end(assign it to particular value) and give the condition in b() according to the flaga variable value. Means something like this...
public a()
{
CheckAll();
}
public b()
{
.
.
(put condition here for check when flaga=1 from the method CheckAll())
CheckAll();
}
public CheckAll()
{
.
.
.
flaga=1;
}
}
Say I have the following code (please assume all the appropriate import statements):
public class CTestClass {
// Properties
protected Object LockObj;
public ConcurrentDictionary<String, String> Prop_1;
protected System.Timers.Timer TImer_1;
// Methods
public CTestClass () {
LockObj = new Object ();
Prop_1 = new ConcurrentDictionary<String, String> ();
Prop_1.TryAdd ("Key_1", "Value_1");
Timer_1 = new System.Timers.Timer ();
Timer_1.Interval = (1000 * 60); // One minute
Timer_1.Elapsed += new ElapsedEventHandler ((s, t) => Method_2 ());
Timer_1.Enabled = true;
} // End CTestClass ()
public void Method_1 () {
// Do something that requires Prop_1 to be read
// But *__do not__* lock Prop_1
} // End Method_1 ()
public void Method_2 () {
lock (LockObj) {
// Do something with Prop_1 *__only if__* Method_1 () is not currently executing
}
} // End Method_2 ()
} // End CTestClass
// Main class
public class Program {
public static void Main (string[] Args) {
CTestClass TC = new CTestClass ();
ParallelEnumerable.Range (0, 10)
.ForAll (s => {
TC.Method_1 ();
});
}
}
I understand it is possible to use MethodBase.GetCurrentMethod, but (short of doing messy book-keeping with global variables) is it possible to solve the problem without reflection?
Thanks in advance for your assistance.
EDIT
(a) Corrected an error with the scope of LockObj
(b) Adding a bit more by way of explanation (taken from my comment below)
I have corrected my code (in my actual project) and placed LockObj as a class property. The trouble is, Method_2 is actually fired by a System.Timers.Timer, and when it is ready to fire, it is quite possible that Method_1 is already executing. But in that event it is important to wait for Method_1 to finish executing before proceeding with Method_2.
I agree that the minimum working example I have tried to create does not make this latter point clear. Let me see if I can edit the MWE.
CODE EDITING FINISHED
ONE FINAL EDIT
I am using Visual Studio 2010 and .NET 4.0, so I do not have the async/await features that would have made my life a lot easier.
As pointed above, you should become more familiar with different synchronization primitives, that exist in .net.
You dont solve such problems by reflection or analyzing whos the concurent - running method, but by using a signaling primitive, which will inform anyone interested that the method is running/ended.
First of all ConcurentDictionary is thread safe so you don't need to lock for producing/consuming. So, if only care about accessing your dictionary no additional locking is necessary.
However if you just need to mutual exclude the execution of method 1 and 2, you should declare the lock object as class member and you may lock each function body using it, but as I said, not needed if you are going to use ConcurentDictionary.
If you really need which method executes at every moment you can use stack frame of each thread, but this will going to be slow and I believe not necessary for this case.
The term you're looking for is Thread Synchronisation. There are many ways to achieve this in .NET.
One of which (lock) you've discovered.
In general terms, the lock object should be accessible by all threads needing it, and initialised before any thread tries to lock it.
The lock() syntax ensures that only one thread can continue at a time for that lock object. Any other threads which try to lock that same object will halt until they can obtain the lock.
There is no ability to time out or otherwise cancel the waiting for the lock (except by terminating the thread or process).
By way of example, here's a simpler form:
public class ThreadSafeCounter
{
private object _lockObject = new Object(); // Initialise once
private int count = 0;
public void Increment()
{
lock(_lockObject) // Only one thread touches count at a time
{
count++;
}
}
public void Decrement()
{
lock (_lockObject) // Only one thread touches count at a time
{
count--;
}
}
public int Read()
{
lock (_lockObject) // Only one thread touches count at a time
{
return count;
}
}
}
You can see this as a sort of variant of the classic readers/writers problem where the readers don't consume the product of the writers. I think you can do it with the help of an int variable and three Mutex.
One Mutex (mtxExecutingMeth2) guard the execution of Method2 and blocks the execution of both Method2 and Method1. Method1 must release it immediately, since otherwise you could not have other parallel executions of Method1. But this means that you have to tell Method2 whene there are Method1's executing, and this is done using the mtxThereAreMeth1 Mutex which is released only when there are no more Method1's executing. This is controlled by the value of numMeth1 which has to be protected by another Mutex (mtxNumMeth1).
I didn't give it a try, so I hope I didn't introduce some race conditions. Anyway it should at least give you an idea of a possible direction to follow.
And this is the code:
protected int numMeth1 = 0;
protected Mutex mtxNumMeth1 = new Mutex();
protected Mutex mtxExecutingMeth2 = new Mutex();
protected Mutex mtxThereAreMeth1 = new Mutex();
public void Method_1()
{
// if this is the first execution of Method1, tells Method2 that it has to wait
mtxNumMeth1.WaitOne();
if (numMeth1 == 0)
mtxThereAreMeth1.WaitOne();
numMeth1++;
mtxNumMeth1.ReleaseMutex();
// check if Method2 is executing and release the Mutex immediately in order to avoid
// blocking other Method1's
mtxExecutingMeth2.WaitOne();
mtxExecutingMeth2.ReleaseMutex();
// Do something that requires Prop_1 to be read
// But *__do not__* lock Prop_1
// if this is the last Method1 executing, tells Method2 that it can execute
mtxNumMeth1.WaitOne();
numMeth1--;
if (numMeth1 == 0)
mtxThereAreMeth1.ReleaseMutex();
mtxNumMeth1.ReleaseMutex();
}
public void Method_2()
{
mtxThereAreMeth1.WaitOne();
mtxExecutingMeth2.WaitOne();
// Do something with Prop_1 *__only if__* Method_1 () is not currently executing
mtxExecutingMeth2.ReleaseMutex();
mtxThereAreMeth1.ReleaseMutex();
}
Imagine you have two buttons on the win form. What do you think should be the behavior when user presses the "button 1" with the below code?
Should it display all 5 message box in one go, or one by one - MessageBox.Show statement is inside a lock statement?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private static readonly object lockobject = new object();
private void button1_Click(object sender, EventArgs e)
{
var action = new Action(function);
for(int i = 0; i< 5; i++)
{
action.BeginInvoke(null, null);
}
}
private void function()
{
if (button2.InvokeRequired)
{
var func = new Action(function);
button2.Invoke(func);
}
else
{
lock (lockobject)
{
MessageBox.Show("Testing");
}
}
}
}
Now if we replace MessageBox.Show with any other statment, it would execute the statement only one at a time, the other threads would wait, one at a time.
Since your lock statement is executed when InvokeRequired is false, the locks will all run on the same (main) thread. Therefore the locks will not block.
If you want the MessageBox to block, use ShowDialog instead.
lock only blocks if another thread owns the lock, locking on the same object from the same thread multiple times is allowed - otherwise it would be an instant deadlock, after all it would have been blocking the current thread while waiting for the current thread.
Control.BeginInvoke doesn't execute code in a different thread, it will always execute the code in the thread pumping messages for the control, it does so by posting a message to the control's input queue and then executing the code when the message arrives.
because of 2 your code isn't multi-threaded at all, everything executes in the same thread - and this brings us back to 1, when you don't have multiple threads lock does nothing.
I suspect the UI thread is pumping messages during the MessageBox life-cycle. Because locks are re-entrant (and the UI thread is running the code each time), this causes the above. Perhaps try passing the owner (this) into the message-box? (I'll try in a sec...).
You could block it more forcefully, but that will block painting ("not responding" etc).
I agree with Nir. After you change your function to the one below, you can test that you are running on the same thread (not surprisingly):
private void function()
{
if (button2.InvokeRequired)
{
var func = new Action(function);
button2.Invoke(func);
}
else
{
lock (lockobject)
{
int threadId = Thread.CurrentThread.ManagedThreadId;
MessageBox.Show("Testing. Running on thread "+threadId);
}
}
}
So here because your UI thread is owing the lock, it doesn't get blocked. The bottom line is that STA threads are not compatible with proper multithreaded programming.