Hello,
Given the following C# multi-threaded interfaces.
Is multi-threaded access via fisher_py available?
from "UsingRawFileReader.pdf"
Multi-threaded code
As noted in the section above, the IRawDataPlus interface is an instance object, and should be used by only one thread.
However, the raw file reader can generate any number of such objects, so that any number of threads can access the
same raw file in parallel.
For multi-threaded code, the pattern is:
A manager object is created (from a file name), which cannot itself read any raw data.
This manager is then used to create IRawDataPlus interfaces for each thread, as detailed below:
The C# raw file reader includes an implementation of IRawFileThreadManager
The factory method RawFileReaderFactory.CreateThreadManager can be used to open a raw file, for use
by multiple threads.
For example:
var myThreadManager = RawFileReaderFactory.CreateThreadManager (path);
This can be used for multi-thread access to the same raw file.
All business logic still accesses the information using the IRawDataPlus interface. Application teams do not have to write
any thread synchronization or locking code.
The usage pattern is as follows.
Open a file returning a thread data manager:
Try
{
myThreadManager = RawFileReaderFactory.CreateThreadManager (filename)
}
Catch exceptions
Exceptions may occur if the required raw file reader dll is not found, or a null string is sent for the raw file name.
The action of opening a file executes a small number of “one time” single threaded actions, such as:
• Opening the file on disk.
• Reading the file header (time stamps, operator name etc.)
• Reading sample information.
• Obtaining the list of detectors.
Important: This “thread manager” cannot itself read any raw data.
Assuming no exceptions, for each thread which needs access to data (including the current thread, if needed):
IRawDataPlus myThreadDataReader = myThreadManager. CreateThreadAccessor();
To test for errors, create a thread accessor.
This property:
///
/// Gets the file error state.
///
IFileError FileError { get; }
Can then be used to check for any errors (such as invalid file name).
Performance Note: Within the C# reader, there is no significant performance overhead in
“CreateThreadAccessor”. In evaluation of this, we have tested that in can be used within a “Parallel.For” pattern,
to make an accessor for each scan in a raw file.
Note: The method “CreateThreadAccessor();” is actually a member of the interface
“IRawFileThreadAccessor” which has other implementations noted later.
After all created threads have exited, call:
myThreadManager.Dispose();
Using this pattern all business logic for multi-threaded code is exactly the same as for single threaded code.
All interface members of IRawDataPlus can be used, with no concerns for locking or thread safety. Do not add any
additional locks in calling code.
Data for each thread is read in parallel (lockless), wherever possible. Some larger objects in the raw file use (thread safe)
lazy loading, such that, for example: The first thread which opens the MS data will incur a small overhead for opening
the MS data stream, then all other threads will share parallel access to that same stream.
Note: Locking may occur when a file is opened in real time mode (during data acquisition), as a real time data is
continually changing state. This locking is internal to the file reader, and calling code need not take any special action for
real time files.
Alternate approaches to threading
Even though the C# reader natively supports parallel access to data, not all file readers may support this, but “There’s an
interface for that”.
The interface “IRawFileThreadManager”
Is defined as follows:
public interface : IRawFileThreadAccessor, IDisposable
That is: When you open a raw file, and obtain this interface, as described above, you “dispose” to close the file.
The mechanism for allocating data to threads is descried in “IRawFileThreadAccessor”, so if the application layer
code opens a file, it may pass “IRawFileThreadAccessor” to the next layer of code.
As above, that code can call “CreateThreadAccessor”:
MyMethod(IRawFileThreadAccessor myThreadDataReader)
IRawDataPlus myThreadDataReader = myThreadDataReader. CreateThreadAccessor();
An advantage of this scheme is that an application can be designed to use other readers which do not support the
thread manager interface, by using another implementation of “IRawFileThreadAccessor”.
CommonCore already includes an implementation of this:
public class ThreadSafeRawFileAccess : IRawCache, IRawFileThreadAccessor
This class permits multi thread support (by IRawFileThreadAccessor) to be generated from any instance of
IRawDataPlus
Using this public constructor:
public ThreadSafeRawFileAccess(IRawDataPlus file).
Via this pattern, library code need not be aware of how the thread management is done. If the library code
(business logic) receives “IRawFileThreadAccessor” it will be able support multi-threaded access to any raw
file, from any file reader.
The difference is one of performance.
When using the C# raw file reader’s direct implementation (ThreadedFileFactory) the business logic will have
lockless parallel access to data. When the interface passed in is created by the class
“ThreadSafeRawFileAccess” then calls into the file are serialized via locks.
Note: In all cases
• The business logic need no add any additional locking.
• The business logic need not reference any specific file reading DLL.
• All required interfaces are contained in ThermoFisher.CommonCore.Data.dll