Multiple thread access to Excel - c#

I have two methods, method1, method2, both have lock(App) where App is a static instance in the same class.
App is a static instance in a shared project Helper
void method1()
{
lock(Helper.App)
{
ExcelApp.FormulaCell.AddComments(errMsg);
}
}
void method2()
{
lock(Helper.App)
{
//plot data (an 2-D array) to cells
var dataRng = ExcelApp.CurrentSheet.Cells(Formulacell.Row + 1, Formulacell.Column + 1);
dataRng = dataRng.get_Resize(n, m);
dataRng.Value2 = data;
}
}
method1, method2 are called by many threads.
I want at one time only method1 or method2 run
The issue is they seem not.
in method1 & method2, I plot some data to Excel, I get Exception
Name:COMException
Message:Exception from HRESULT: 0x800AC472
I googled and find the exception is caused by Excel Application is not ready.
There is no UI gesture, so I conclude the exception is caused by the two methods try to write to Excel at the same time.

Please check if youre calling an async methods to excell.
If so, this is the problem, even though you used locks, the actual calls are running in the same time.
Try to wait till the excell methods ends.
Ofir

Related

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.

Detect Boolean value changes inside Thread

I have a c++ dll function that i want to run inside the C# thread.
Some times I need to cancel that thread, and here is the issue :
Thread.Abort() is evil from the multitude of articles I've read on
the topic
The only way to do that was to use a bool and check it's value periodically.
My problem that even i set this value to true it didn't change and still equal to false in c++ code. However when I show a MessageBox that value changed and it works fine.
Any ideas why that value changed only when the MessageBox showed and please tell me how to fix that issue.
C#
public void AbortMesh()
{
if (currMeshStruct.Value.MeshThread != null && currMeshStruct.Value.MeshThread.IsAlive)
{
//here is my c++ Object and cancel mesh used to set bool to true;
MeshCreator.CancelMesh();
}
}
C++
STDMETHODIMP MeshCreator::CancelMesh(void)
{
this->m_StopMesh = TRUE;
return S_OK;
}
when I test the boolean value
if (m_StopMesh)
return S_FALSE;
The value here is always false even i call AbortMesh()
if (m_StopMesh)
return S_FALSE;
MessageBox(NULL,aMessage,L"Test",NULL);
if (m_StopMesh) // here the value is changed to true
return S_FALSE;
The non-deterministic thread abortion (like with Thread.Abort) is a really bad practice. The problem is that it is the only practice that allows you to stop your job when job does not know that it could be stopped.
There is no library or framework in .NET I know of that allows to write threaded code that could allow you to run an arbitrary task and abort it at any time without dire consequences.
So, you was completely write when you decided to use manual abort using some synchronization technique.
Solutions:
1) The simplest one is using of a volatile Boolean variable as it was already suggested:
C#
public void AbortMesh()
{
if (currMeshStruct.Value.MeshThread != null && currMeshStruct.Value.MeshThread.IsAlive)
{
MeshCreator.CancelMesh();
}
}
C++/CLI
public ref class MeshCreator
{
private:
volatile System::Boolean m_StopMesh;
...
}
STDMETHODIMP MeshCreator::CancelMesh(void)
{
this->m_StopMesh = TRUE;
return S_OK;
}
void MeshCreator::ProcessMesh(void)
{
Int32 processedParts = 0;
while(processedParts != totalPartsToProcess)
{
ContinueProcessing(processedParts);
processedParts++;
if (this->m_StopMesh)
{
this->MakeCleanup();
MessageBox(NULL,aMessage,L"Test",NULL);
}
}
}
Such code should not require any synchronization if you do not make any assumptions on completion of thread after the CancelMesh call - it is not instantaneous and may take variable amount of time to happen.
I don't know why the use of the volatile didn't help you, but there are few moments you could check:
Are you sure that the MeshCreator.CancelMesh(); method call actually happen?
Are you sure that m_StopMesh is properly initialized before the actual processing begins?
Are you sure that you check the variable inside the ProcessMesh often enough to have decent response time from your worker and not expecting something instantaneous?
2)Also if you use .NET 4 or higher you could also try to use the CancellationToken-CancellationTokenSource model. It was initially designed to work with Tasks model but works well with standard threads. It won't really simplify your code but taking into an account the async nature of your processing code will possibly simplify future integration with TPL
CancellationTokenSource cancTokenSource = new CancellationTokenSource();
CancellationToken cancToken = cancTokenSource.Token;
Thread thread = new Thread(() =>
{
Int32 iteration = 0;
while (true)
{
Console.WriteLine("Iteration {0}", iteration);
iteration++;
Thread.Sleep(1000);
if (cancToken.IsCancellationRequested)
break;
}
});
thread.Start();
Console.WriteLine("Press any key to cancel...");
Console.ReadKey();
cancTokenSource.Cancel();
3) You may want to read about interlocked class,monitor locks, autoresetevents and other synchronization, but they are not actually needed in this application
EDIT:
Well, I don't know how it couldn't help(it is not the best idea, but should work for such a scenario), so I'll try later to mock your app and check the issue - possibly it has something to do with how MSVC and CSC handle volatile specifier.
For now try to use Interlocked reads and writes in your app:
public ref class MeshCreator
{
private:
System::Boolean m_StopMesh;
...
}
STDMETHODIMP MeshCreator::CancelMesh(void)
{
Interlocked::Exchange(%(this->m_StopMesh), true);
return S_OK;
}
void MeshCreator::ProcessMesh(void)
{
Int32 processedParts = 0;
while(processedParts != totalPartsToProcess)
{
ContinueProcessing(processedParts);
processedParts++;
if (Interlocked::Read(%(this->m_StopMesh))
{
this->MakeCleanup();
MessageBox(NULL,aMessage,L"Test",NULL);
}
}
}
P.S.: Can you post the code that actually processes the data and checks the variable(I don't mean your full meshes calculations method, just its main stages and elements)?
EDIT: AT LEAST IT'S CLEAR WHAT THE SYSTEM IS ABOUT
It is possible that your child processes are just not exterminated quick enough. Read this SO thread about process killing.
P.S.: And edit your question to more clearly describe your system and problem. It is difficult to get the right answer to a wrong or incomplete question.
Try putting volatile before the field m_StopMesh:
volatile BOOL m_StopMesh;
I launched the c++ process using a thread and it worked fine.
If you want to communicate across process boundaries, you will need to use some sort of cross-process communication.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx
I find Named Pipes convenient and easy to use.
UPDATE
Your comment clarifies that the C++ code is running in-process.
I would suggest a ManualResetEvent. For a great overview of thread synchronization (and threads in general) check out http://www.albahari.com/threading/

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.

Passing Data Between Threads

I have the following code, in which I’m trying to process a large amount of data, and update the UI. I’ve tried the same thing using a background worker, but I get a similar issue. The problem seems to be that I’m trying to use a class that was not instantiated on the new thread (the actual error is that the current thread doesn't "own" the instance). My question is, is there a way that I can pass this instance between threads to avoid this error?
DataInterfaceClass dataInterfaceClass = new DataInterfaceClass();
private void OutputData(List<MyResult> Data)
{
progressBar1.Maximum = Data.Count;
progressBar1.Minimum = 1;
progressBar1.Value = 1;
foreach (MyResult res in Data)
{
// Add data to listview
UpdateStatus("Processing", res.Name);
foreach (KeyValuePair<int, string> dets in res.Details)
{
ThreadPool.QueueUserWorkItem((o) =>
{
// Get large amount of data from DB based on key
// – gives error because DataInterfaceClass was
// created in different thread.
MyResult tmpResult = dataInterfaceClass
.GetInfo(dets.DataKey);
if (tmpResult == null)
{
// Updates listview
UpdateStatus("Could not get details",
dets.DataKey);
}
else
{
UpdateStatus("Got Details", dets.DataKey);
}
progressBar1.Dispatcher.BeginInvoke(
(Action)(() => progressBar1.Value++));
});
}
}
}
EDIT:
DataInterfaceClass is actually definated and created outside of the function that it is used in, but it is an instance and not static.
UPDATE:
You seem to have modified the posted source code, so...
You should create an instance of the DataInterfaceClass exclusively for each background thread or task. Provide your task with enough input to create its own instance.
That being said, if you try to access data in a single database in a highly parallel way, this might result in database timeouts. Even if you can get your data access to work in a multithreaded way, I would recommend limiting the number of simultaneous background tasks to prevent this from occurring.
You could use a Semaphore (or similar) to ensure that no more than a certain amount of tasks are running at the same time.
Create a global instance for DataInterfaceClass inside the class that has OutputData method defined, that way you would be able to use it within the method.
However, you would need to be cautious in using it. If all the threads would use the same instance to read from the database, it would result in errors.
You should either create a new instance of the DataInterfaceClass in each thread, or have some lock implemented inside your GetInfo method to avoid multiple access issues.

Need help with weird Begin/EndInvoke issue which Causes "Thread Leak"

I got following code executing at a ~1000ms rate. Left alone, it causes a weird "thread leak". Using WindDBG/SoS I am able to see waaay to many ThreadPool Worker threads (some of them are marked as dead) and eventually I will get a AccessVioalation Exception. Can anybody tell me if my BeginInvoke/EndInvoke use is wrong, unnecessary lock perhaps ... any clues will help as I am ... well, clueless at this point
RichTextBox tmpBox = txtIncomingData;
lock (m_TextUpdateSynch) {
try {
result = Utilities.SafeBeginInvoke(this, delegate() {
try {
if (tmpBox.Text.Length > BufferSize) {
tmpBox.Text = rawData;
}
else {
tmpBox.AppendText(rawData);
}
pageBottom(txtIncomingData);
}
catch (...) {}
});
this.EndInvoke(result);
}
public static IAsyncResult Utilities.SafeBeginInvoke(System.ComponentModel.ISynchronizeInvoke control,
ControlUpdate action, AsyncCallback callback,
params object[] args) {
IAsyncResult result = null;
Control uiControl = control as Control;
try {
result = control.BeginInvoke(action, args);
}
catch (...) { }
return result;
}
It looks like your code is using WPF, and it's my understanding that in WPF BeginInvoke will marshall the call you;re making to the UI (Dispatcher) thread; so it shouldn't be creating any extra threads as far as I'm aware.
http://msdn.microsoft.com/en-us/library/ms591206.aspx
I notice your try/catch pairs around the BeginInvoke call too; this suggests to me that you've been getting exceptions thrown by that, and I'd suggest that getting to the root of them might be a better plan than suppressing them. For example you seem to be referencing three variables - BufferSize, rawData, txtIncomingData which are defined outside of your lock - if any other code has a reference to them and is modifying them on a different (non-UI) thread then that could be causing your issues.
Lastly, I think the overload of SafeBeginInvoke you listed isn't the one being called by the code - the one listed takes 4 parameters (although one is params), the one you call takes 2.

Categories