I have a application that sends out a few 100k emails each night, so to speed processing added some cfthreads.
This has caused some strange errors, and I've found that a variable created in one thread is being modified by another thread. From the documentation I've read, variables created in one thread should be visible only to that thread?
Made a simple test like so:
<cfthread
name="thread1"
action="run">
<cfsavecontent variable="local.template_body">
<cfinclude template="templates\6\2\bulletin_template.cfm">
</cfsavecontent>
<cfset tmpEmailBody = template_body>
</cfthread>
<cfthread
name="thread2"
action="run">
<cffile action="append"
file="C:\inetpub\error1.txt"
output="#tmpEmailBody#">
</cfthread>
The contents of "tmpEmailBody" successfully get written to the file.
The strange thing is if i remove the cfsavecontent section, and have:
<cfset tmpEmailBody = "test">, then the second thread raises and error that tmpEmailBody isnt defined, as I would expect.
Anyone know what's going on here?
I believe your running cfthread for the wrong purpose. It seems that the tmpEmailBody in thread 2 is dependent on thread1. You should not run dependent code in separate threads..
A better use of cfthread as pertaining to mailing may be
Thread1 {
select Emails from database where emails start from a-m
out your list of a-m
}
Thread 2 {
select Emails from database where emails start from n-z}
out your list n-z
}
Both of your threads run at the same time. The 2 queries can take place at the same time, but you cant save variables in 1 thread and hope that it matches up your call timing in another thread.
The variable tmpEmailBody is being created in the Variables scope, not in a scope that is limited to the thread. The threads will execute in random order and random times, so the error is caused because thread1 hasn't executed its last line before thread2 executes its first line.
All of the normal scopes are not thread safe when using cfthread (as opposed to being thread safe for ColdFusion request threads; aka page threads) If you want to make sure that a variable created/used in one thread is isolated from all other threads then you must use thread scoping. This is officially documented as Using thread data in the ColdFusion documentation.
I would have guessed that you were declaring tmpEmailBody outside of the two threads, but since changing the cfset to a static string gives the expected behaviour I would say there's an "issue" with cfsavecontent and it's writing to the Variables scope instead of thread-local scope, which should be filed as another scoping gotcha.
Since the ColdFusion documentation examples leave a bit to be desired I'll rewrite your code as if you wanted to pass the email body from one thread to the other. You've said this isn't your intended use, but it will show the various thread scopes. The following code copies values into different scopes when it doesn't need to, but done to hopefully make the different scopes more clear. And, as others have stated, the below task is a poor use of threads.
<cfthread
name="thread1"
action="run">
<cfset var template_body = "">
<cfsavecontent variable="template_body">
<cfinclude template="templates\6\2\bulletin_template.cfm">
</cfsavecontent>
<cfset thread.tmpEmailBody = template_body>
</cfthread>
<cfthread action="join" name="thread1" timeout="60">
<cfset Variables.tmpEmailBody = cfthread["thread1"]tmpEmailBody>
<cfthread
name="thread2"
action="run"
emailBody="#Variables.tmpEmailBody#">
<cffile action="append"
file="C:\inetpub\error1.txt"
output="#Attributes.emailBody#">
</cfthread>
Related
we have an issue in MFC-based application related to “current MFC state” and threads. In main thread we call VisualManager, because we want to have fancy toolbars. The call ends up in CMFCVisualManagerOffice2007::OnUpdateSystemColors function located inside afxvisualmanageroffice2007.cpp, which changes “current resource handle” by calling AfxSetResourceHandle function. This function gets “current module state” and changes “current resource handle” from MyApp.exe to mfc140u.dll. This is fine, because assets for VisualManager are located in that DLL and the change will be restored back to MyApp.exe in all cases.
However, what is not fine is that we spawn a new thread just before call to VisualManager (by using AfxBeginThread), this thread needs to load some strings from string table (by using CString class), but it sometimes fails to do so. It fails because there is race with main thread about AFX_MODULE_STATE::m_hCurrentResourceHandle variable. The thread expect it to be set to MyApp.exe, but the main thread changes it to mfc140u.dll and back, the “current resource handle” is effectively a global variable.
So, my questions are: 1) Are we doing something obviously wrong managing our MFC-based threads? Should we somehow copy or protect the “module state” so our new thread is immune to the change main thread is doing? Should aim MFC to create something like per-thread variable / state? 2) I believe Microsoft is wrong here, changing what is effectively a global variable and screwing other threads expectations, VisualManager should obtain the handle and pass it to all its functions as a parameter. Am I right?
EDIT:
Hi guys #iinspectable, #cha, I have an update, sorry it took so long. Steps to reproduce: Open Visual Studio 2015 Update 3, Create new MFC application through the wizard, make sure it has the "Project style" and "Visual style and colors" selected as "Office" and "Office 2007 (Blue theme)". Open file afxvisualmanageroffice2007.cpp from MSVS folder and put 4 break-points into CMFCVisualManagerOffice2007::OnUpdateSystemColors function where it calls AfxSetResourceHandle. Open file MFCApplication1.cpp in your newly created project folder and put this code [1] into CMFCApplication4App::InitInstance function just before CMainFrame* pMainFrame = new CMainFrame;, put break-point into this thread proc.
Now build and run this MFC application in debug mode, on each break-point hit, use freeze thread and thaw thread functions from Threads window, so you will arrange main thread in the middle of CMFCVisualManagerOffice2007::OnUpdateSystemColors function just after setting the global variable using AfxSetResourceHandle function and the worker thread before CStringT::LoadString. Now the load string will fail because it is looking for it inside mfc140ud.dll instead of using resource chain and MFCApplication1.exe.
I believe this is Microsoft's bug (changing global variable for a while), my code-base is full of innocent CString::LoadString calls which rely on carefully and correctly constructed resource chain with various plug-in DLLs and with an .exe at the end. If this is not Microsoft's bug then it is my bug relying on MFC on providing me a usable resource chain. I would need to create my own resource-chain-like functionality and use it everywhere when loading strings and other stuff from resources.
// [1]
AFX_THREADPROC thread_proc = [](LPVOID pParam){
CString str;
str.LoadString(IDS_CAPTION_TEXT);
UINT ret = 0;
return ret;
};
::AfxBeginThread(thread_proc, (LPVOID)nullptr);
// Same result with ::AfxBeginThread(CRuntimeClass*) overload.
My current application is using single instance of an object as a global variable for many of the main components, which I understand is considered inferior to using dependency injection.
I wish to make my applications open source in the future, but first I want to refactor the code to use the most recommended techniques for team collaboration so that other developers will be able to change my source code more easily.
Example of a shared resource: In the CFML language, you have the Server scope, which is shared memory that is available to any request for the entire server instance.
Here is my new design concept for managing changes to the Server scope:
Create a single instance of component named ServerMemoryManager which provides an interface for writing and reading to the server scope.
Any other code that needs to access the server scope will be injected with a reference to the single instance of the ServerMemoryManager via an init() function or a setServerMemoryManager() function.
Whenever a component reads/writes data to the ServerMemoryManager object, it will be able to internally lock the server scope so that no 2 threads can simultaneous write to the same piece of memory in the server scope.
Is this the best way to manage a shared resource (shared memory, filesystem, etc) that requires locking in order to be thread-safe?
Please describe any additional methods that can be used to manage a shared resource that requires locking during certain read/write operations which are considered best practices.
Edit: Based on the accepted answer, instead of locking scope="server", I will use named locks and manage the shared resources with more fine-grained locking. This may allow using multiple objects to manage the shared resources assuming they are all managing different keys in shared memory or files in the filesystem. For example, one application could have its own unique key or directory assigned to it so that it wouldn't conflict with another application trying to change a shared resource.
Edit2: I found I could use a single component named scope.cfc for each scope if I pass the scope into the init function when I create the object. I am now using fine-grained named locks. Let me know if it can be improved. The actual revised code now looks like this (I excluded the code for read, delete, clear). It also doesn't seem that it is required to have a single instance of the scope.cfc component anymore.
<cfcomponent>
<cfscript>
variables.scope=false;
variables.scopeName=false;
</cfscript>
<cffunction name="init" access="public" output="no" returntype="scope">
<cfargument name="scope" type="struct" required="yes">
<cfargument name="scopeName" type="string" required="yes">
<cfscript>
variables.scope=arguments.scope;
variables.scopeName=arguments.scopeName;
return this;
</cfscript>
</cffunction>
<cffunction name="write" access="public" output="no" returntype="boolean">
<cfargument name="key" type="string" required="yes">
<cfargument name="value" type="any" requires="yes">
<cfargument name="timeout" type="numeric" required="no" default="10">
<cftry>
<cflock type="exclusive" name="zcore-#variables.scopeName#-scope-#arguments.key#" timeout="#arguments.timeout#" throwontimeout="yes">
<cfscript>
variables.scope[arguments.key]=arguments.value;
</cfscript>
</cflock>
<cfcatch type="lock"><cfreturn false></cfcatch>
</cftry>
<cfreturn true>
</cffunction>
</cfcomponent>
** Edit3:** I tested the performance of reading from server scope through a component method like this and found it to be 20 times slower then reading the server scope directly when using a read only lock and 4 times slower without a lock. The overhead of an extra function call hundreds or thousands of times per request will be too slow. Tests done on Railo 3.3.x.
I prefer to build a large object in a non-public request and then set a single shared memory scope key then try to write an incomplete object to the scopes. Example:
<cfscript>
ts=structnew();
ts.largeObject=buildLargeObject();
server.cachedObject=ts;
</cfscript>
This lets you avoid locking across the entire application when you only write complete objects to shared memory since updating a single struct key is thread-safe. However, when you build the large object on startup, you need to be sure it is locked until that object is fully created.
I'm going to make the scope variable become directly readable by using the this scope instead of variables scope in the init function to avoid slowing down the application.
CFLOCK only prevents code from executing if every occurrence is locked the same way.
For example:
page1.cfm
<cflock type="exclusive" scope="server" timeout="10" >
<cfset application.xyz = 'abc'>
</cflock>
page2.cfm
<cfset application.xyz = '123'>
Page2.cfm is going to negate any locks you have on page1.cfm if page2 runs the same time page1 does. That said, it's good that you are locking inside your cfc so that each object doesn't have to be locked.
However, locking every occurrence isn't enough. The following won't do much good either.
page1.cfm
<cflock type="exclusive" scope="server" timeout="10" >
<cfset application.xyz = 'abc'>
</cflock>
page2.cfm
<cflock type="exclusive" scope="server" timeout="10" >
<cfset application.xyz = '123'>
</cflock>
This will halt the processing for every request of page1 and page2 but will not protect application.xyz on page1 from changes made to application.xyz on page2. To do this you need to give your locks a "name".
Locks name. Mutually exclusive with the scope attribute. Only one
request can execute the code within a cflocktag with a given name at a
time. Cannot be an empty string.
Permits synchronizing access to resources from different parts of an
application. Lock names are global to a ColdFusion server. They are
shared among applications and user sessions, but not clustered
servers.
Because you are creating multiple instances of your object, I believe serverMemoryManagerObject could interfere with serverMemoryManagerObject2 unless you name your lock.
Here is some more information about locking dos and don'ts
Locking code with cflock
CFLock And Negative Outcomes Think It Through
CFMythbusters - Countering Some Conventional Wisdom
Is it possible to print in Silverlight without blocking the UI thread?
I have to print a lot of pages, and consequently my UI freezes for a while. I would like to print on a background thread instead (and update a progress bar if possible), but can't figure out how.
I tried calling the Print() method of my PrintDocument inside the DoWork() method of a BackgroundWorker, but that gives me an UnauthorizedAccessException "Invalid cross-thread access".
It seems that even initiating a PrintDocument is not possible outside the UI thread:
PrintDocument pd = new PrintDocument(); in BackgroundWorker.DoWork() throws the same exception.
I found a lot of posts where people say that printing has to happen on the UI thread, but no documentation of this. I'm new to multithreading, so any pointers in the right direction would be appreciated.
I had this problem and came across this question which unfortunately didn't have the answer i was hoping for. But I thought that for anyone else who comes across this problem, this may at least shed some light.
I was following this article on printing in Silverlight, It works like a charm for regular printing on the UI Thread, but for actually trying to print on a separate thread I don't think it's possible. I switched out the last line of code in the example
printDocument.Print("SLPrintDemo document");
with an alternate one to see if it would work
new Thread(() => printDocument.Print("SLPrintDemo document")).Start();
To see if the print job itself would spawn in a separate thread. However though the code compiles and runs fine, the document does not print. The reason seems to be that once the Print command is fired, it then fires up the printing options dialog for choosing printer and other options etc. At this point it is no longer on the UI thread so nothing happens ( No exceptions, so i'm assuming they're swallowed somewhere)
So as far as I can tell at the moment, there is no way to print in Silverlight that is not in the UI thread.
Use Dispatcher for updating your UI. For example:
Dispatcher.BeginInvoke(() =>
{
ProgressBar.Value = 100;
});
I have a thread, called TAlertThread. The thread interacts with its owner by triggering events. For example, when certain data is available inside the thread, it sets some temp variables and calls Synchronize(UpdateAlert) which in turn triggers the appropriate event.
Now the thread works perfectly in any standard windows application. My problem is when I put that thread inside of an ActiveX form (TActiveForm). The ActiveX control (aka COM object) is then embedded inside of a Windows Desktop Gadget (via HTML / Javascript). I also have experience with this, the gadget is not the issue. The ActiveX component works fine in its destination, except the thread is never executed. It's even being called EXACTLY the same way as I called it from the App.
Is this some limitation with ActiveX, blocking threads from executing? I wouldn't think so, because other things that require threads internally (such as TADOConnection) work. I am in fact properly calling CoInitialize and CoUninitialize appropriately. Again, works perfect in an application, but does not work at all in ActiveX.
Here is how I call this thread...
procedure TRMPDashXS.ExecThread;
begin
//Thread created suspended
lblStatus.Caption:= 'Executing Thread...';
fThread:= TAlertThread.Create(fConnStr); //fConnStr = connection string
fThread.Priority:= tpIdle;
fThread.OnConnect:= Self.ThreadConnected;
fThread.OnDisconnect:= Self.ThreadDisconnected;
fThread.OnBegin:= Self.ThreadStarted;
fThread.OnFinish:= Self.ThreadFinished;
fThread.OnAlert:= Self.ThreadAlert;
fThread.OnAmount:= Self.ThreadAmount;
fThread.Resume; //Execute the thread
end;
I suspect this might describe exactly what you're experiencing in your version of Delphi:
http://soft-haus.com/blog/2009/02/10/codegear-borland-activex-threading-synchronization-problems/
which references the same article you cited:
http://edn.embarcadero.com/article/32756
I'm not sure if that helps ... but I hope it does. At least a little :)
PS:
Is there any particular reason you have to use Com/ActiveX and/or TActiveForm?
According to this article here: http://edn.embarcadero.com/article/32756 web browsers don't allow threading via ActiveX. However that still doesn't explain why it doesn't work when I put it in a C# application.
Here is my problem , I have created a SortableCollection : ObservableCollection
and added a sort method (sort colors).
When I sort The collection with the principal Thread , it works every thing is fine and works
But When I try to sort this customCollection by using an item in the collection I have an expetion : (The calling thread cannot access this object because a different thread owns it).
I have looked in web and I found several solution , One Solution
This type of solution put the collection multithread for insertion , removing moving operation.
But not for the custom sort.
Thanks for help,
WPF classes have thread affinity. What this means is that all changes to those objects must be in the same thread where they were created. It truly is difficult to create a user interface API that is thread-safe, so Microsoft chose to keep it singlethreaded and force run-time checking to make sure of it.
That said, there are a few options you have to perform your sort in a background thread, and then apply it in the UI thread. The first option is to copy your SortableCollection into a plain old List or Array and perform the sort in the background. Once the background thread is complete, you use a Dispatcher to execute code in the UI thread. Every UI element in WPF extends System.Windows.Threading.DispatcherObject and most extend System.Windows.Freezable. The DispatcherObject is where you get the Dispatcher to execute code in the UI thread.
Logically, the execution would be something like this:
public void BackgroundSort()
{
List<T> items = new List<T>(this.ToArray());
BackgroundSortDelegate del = Sort;
del.BeginInvoke(SortCompleted, del);
}
private void SortCompleted(IAsyncResult result)
{
BackgroundSortDelegate del = result.AsyncState as BackgroundSortDelegate;
List<T> items = del.EndInvoke(result);
this.Dispatcher.Invoke(()=>{this.Collection = items;});
}
The short explanation of what happened is that the background worker/delegate is using a copy of the items in this list. Once the sort is complete, we are calling the Dispatcher object and invoking an action. In that action we are assigning the new sorted list back to our object.
The key to assigning the result of any background work within the UI thread is to use the UI's Dispatcher object. There's actually probably a half dozen ways to invoke a background worker in C#, but the approach to get your work in a background thread into the UI thread is the same.