imagine you have a function that creates/copies/moves files. [logic]
For the case that a file that should be copied/created already exists you would like to ask the user to overwrite the file or not.[(G)UI]
What is your approach to implement this if (G)UI and logic are completely separated?
The first thing that comes into my mind would be the MVC-pattern, but this means that I would have to use it whereever I need user interaction.
Any other suggestions?
BTW: How would you implement this in non-OO-languages?
If GUI and logic are really separated, then this question should never arise. The program should, by design, either overwrite or not overwrite based on an option which has a default value. If the GUI is available, the option can be set.
In fact, although the obvious approach is to just have at it and begin copying, you could make a first pass looking for conflicts, and checking that the target device has enough free storage. Then, if there is a problem, terminate by doing nothing, unless there is a GUI in which case you can report the problem and ask whether to proceed anyway.
If you want to have a design in which the GUI can be invoked on a file by file basis, then design the logic around that as a set of n processes each of which copies one file, and has an optional GUI available in the error reporting section. The GUI can then reinvoke the copy-one-file logic.
I can see two ways:
You have two functions, file_exists(...) and copy_file(...). The UI side always calls file_exists first and asks the user whether to copy the file is it already exists.
You have only one function copy_file(bool force, ...), that by default fails if the file exists. So UI side calls the default version of the function, check if it failed and why, if it was because the file already exists, ask the user and try again with force=true.
In a Non OO language I would implement some kind of event queue where the parent (or child, depending on your design) UI polled for events while a 'busy' flag was true. Such an event lets the other side do other work while waiting for a 'they answered' flag to come true. Of course, some timeout in both directions would have to be observed as well as mutual exclusion. Basically, imply the principles of non-blocking I/O or your favorite theory on practical lock free programming here.
There are degrees of separation .. processes can communicate. Depending on your language of choice, you have shared memory segments, semaphores .. or IPC via relational DB with primitive signals. Its hard to be more specific with such a generic question.
See my comment, a little more information is needed so an answer can be crafted that works within your language of choice.
The first thing that comes into my mind would be the MVC-pattern, but this means that I would have to use it wherever I need user interaction.
And this is a bad thing why? Separating GUI and logic is exactly what the MVC pattern is for. Don't be scared of it just because it a has a long name -- as soon as you've separated GUI and logic you have a "view" and a "controller", at least, if not a "model" -- and if your application has state, you've got a model too. You just may not have admitted it to yourself yet.
From what I can see, there are really two problems:
We have an algorithm (logic) in which we would like to defer some operations and decisions to something else (e.g. user via UI).
We would like to avoid tight coupling between the algorithm and that something else.
If we use OO languages, there are several design patters which address these two specific problems.
Template Method pattern can solve #1. It does not solve #2 very well because the typical implementation is via inheritence.
Observer pattern looks promising too.
So really it is choosing and mixing the simplest one for the needs and most suitable for the language.
In practical terms, if talk about C# for example, we can implement Template Method and Observer hybrid like this:
// This will handle extensions to the FileCopy algorithm
abstract class FileCopyExtention
{
public abstract Response WhatToDoWhenFileExists();
}
// the copy function, pure logic
public static void Copy(string source, string destination, FileCopyExtention extension)
{
if (File.Exists(destination))
{
var response = _extension.WhatToDoWhenFileExists();
if (response == overwrite)
// overwrite the file
else
// error
}
}
// This is our user-interactive UI extension
class FileCopyUI : FileCopyExtention
{
public override Response WhatToDoWhenFileExists()
{
// show some UI, return user's response to the caller
}
}
// the program itself
void Main()
{
Copy("/tmp/foo", "/tmp/bar", new FileCopyUI());
}
As a variation of the theme, you can use events, delegates or whatever the language of your choice provides.
In C, this could be a function pointer, in C++ a reference to a class I guess.
What about this approach [pseudo-code]:
UIClass
{
//
// Some code
//
bool fileCopied = false;
do {
try {
fileCopied = CopyFile(fileName);
} catch (FileExists) {
//
// Ask "File exists! Overwrite?" If "No", exit do-loop
//
} catch (FileLocked) {
//
// Ask "File Locked! Repeat?", If "No", exit do-loop
//
} catch (etc...) {
//
// etc.
//
}
} while (!fileCopied);
//
// Some code
//
}
LogicClass
{
//
// Some code
//
bool CopyFile(string fileName)
{
//
// copy file
//
}
//
// Some code
//
}
Related
I'm begginer in multithreading. I recently started to writing something like multithreaded observer. I need some clarification.
Let's say I'm working with Subject, and I'm changing its state. Then Observers (in example - GUI widgets) have to be notified, so they could perform the update() method.
And there is my question: how am i handling those getValue() performed by many Observers? If it's just a getter for some variable, do i have to run it in new thread? Does it require any locking?
Or mayby there is a metod to just send those new value to GUI thread, and letting widgets there access those value. And again, can it be a single loop, or do i have to create another threads for every widget to get those value?
That's a difficult subject. Here are couple of things that will guide and help you with it.
Embrace eventual consistency. When one object updates on one thread, others will receive change notifications and update to the correct state eventually. Don't try to keep everything in sync all the time. Don't expect everything to be up to date all the time. Design your system to handle these situations. Check this video.
Use immutability especially for collections. Reading and writing to a collection from multiple threads can result in disasters. Don't do it. Use immutable collections or use snapshotting. Basically one object that will called from multiple thread will return a snapshot of the state of the collection. when a notification for a change is received, the reader (GUI in your case) will request a snapshot of the new state and update it accordingly.
Design rich Models. Don't use AnemicModels that have only setters and getters and let others manipulate them. Let the Model protect it's data and provide queries for it's state. Don't return mutable objects from properties of an object.
Pass data that describes changes with change notifications. This way readers (GUI) may sync their state only from the change data without having to read the target object.
Divide responsibility. Let the GUI know that it's single threaded and received notifications from the background. Don't add knowledge in your Model that it will be updated on a background thread and to know that it's called from the GUI and give it the responsibility of sending change requests to a specific thread. The Model should not care about stuff like that. It raises notifications and let subscribers handle them the way they need to. Let the GUI know that the change notification will be received on the background so it can transfer it to the UI thread.
Check this video. It describes different way you can do multithreading.
You haven't shown any code or specified language, so I'll give you an example in pseudo code using a Java/C# like language.
public class FolderIcon {
private Icon mIcon;
public Icon getIcon() { return mIcon; }
public FolderIcon(Icon icon) {
mIcon = icon;
}
}
public class FolderGUIElement : Observer {
private Folder mFolder;
private string mFolderPath;
public FolderGUIElement(Folder folder) {
mFolder = folder;
mFolderPath = mFolder.getPath();
folder.addChangeListener(this);
}
public void onSubjectChanged(change c) {
if(c instanceof PathChange) {
dispatchOnGuiThread(() => {
handlePathChange((PathChange)change);
});
}
}
handlePathChange(PathChange change) {
mFolderPath = change.NewPath;
}
}
public class Folder : Subject {
private string mPath;
private FolderIcon mIcon;
public string getPath() { return mPath; }
public FolderIcon getIcon() { return mIcon; }
public void changePath(string newPath) {
mPath = patnewPath;
notifyChanged(new PathChange(newPath));
}
public void changeIcon(FolderIcon newIcon) {
mIcon = newIcon;
notifyChanged(new IconChange(newIcon));
}
}
Notice couple of things in the example.
We are using immutable objects from Folder. That means that the GUI elements cannot get the value of Path or FolderIcon and change it thus affecting Folder. When changing the icon we are creating a brand new FolderIcon object instead of modifying the old one. Folder itself is mutable, but it uses immutable objects for it's properties. If you want you can use fully immutable objects. A hybrid approach works well.
When we receive change notification we read the NewPath from the PathChange. This way we don't have to call the Folder again.
We have changePath and changeIcon methods instead of setPath and setIcon. This captures the intent of our operations better thus giving our model behavior instead of being just a bag of getters and setters.
If you haven't read Domain Driven Design I highly recommend it. It's not about multithreading, but on how to design rich models. It's in my list of books that every developer should read. On concept in DDD is ValueObject. It's immutable and provide a great way to implement models and is especially useful in multithreaded systems.
I have written an Event Sourced Aggregate and now implemented an Event Sourced Saga... I have noticed the two are similair and created an event sourced object as a base class from which both derive.
I have seen one demo here http://blog.jonathanoliver.com/cqrs-sagas-with-event-sourcing-part-ii-of-ii/ but feel there may be an issue as Commands could be lost in the event of a process crash as the sending of commands is outside the write transaction?
public void Save(ISaga saga)
{
var events = saga.GetUncommittedEvents();
eventStore.Write(new UncommittedEventStream
{
Id = saga.Id,
Type = saga.GetType(),
Events = events,
ExpectedVersion = saga.Version - events.Count
});
foreach (var message in saga.GetUndispatchedMessages())
bus.Send(message); // can be done in different ways
saga.ClearUncommittedEvents();
saga.ClearUndispatchedMessages();
}
Instead I am using Greg Young's EventStore and when I save an EventSourcedObject (either an aggregate or a saga) the sequence is as follows:
Repository gets list of new MutatingEvents.
Writes them to stream.
EventStore fires off new events when streams are written to and committed to the stream.
We listen for the events from the EventStore and handle them in EventHandlers.
I am implementing the two aspects of a saga:
To take in events, which may transition state, which in turn may emit commands.
To have an alarm where at some point in the future (via an external timer service) we can be called back).
Questions
As I understand event handlers should not emit commands (what happens if the command fails?) - but am I OK with the above since the Saga is the actual thing controlling the creation of commands (in reaction to events) via this event proxy, and any failure of Command sending can be handled externally (in the external EventHandler that deals with CommandEmittedFromSaga and resends if the command fails)?
Or do I forget wrapping events and store native Commands and Events in the same stream (intermixed with a base class Message - the Saga would consume both Commands and Events, an Aggregate would only consume Events)?
Any other reference material on the net for implementation of event sourced Sagas? Anything I can sanity check my ideas against?
Some background code is below.
Saga issues a command to Run (wrapped in a CommandEmittedFromSaga event)
Command below is wrapped inside event:
public class CommandEmittedFromSaga : Event
{
public readonly Command Command;
public readonly Identity SagaIdentity;
public readonly Type SagaType;
public CommandEmittedFromSaga(Identity sagaIdentity, Type sagaType, Command command)
{
Command = command;
SagaType = sagaType;
SagaIdentity = sagaIdentity;
}
}
Saga requests a callback at some point in future (AlarmRequestedBySaga event)
Alarm callback request is wrapped onside an event, and will fire back and event to the Saga on or after the requested time:
public class AlarmRequestedBySaga : Event
{
public readonly Event Event;
public readonly DateTime FireOn;
public readonly Identity Identity;
public readonly Type SagaType;
public AlarmRequestedBySaga(Identity identity, Type sagaType, Event #event, DateTime fireOn)
{
Identity = identity;
SagaType = sagaType;
Event = #event;
FireOn = fireOn;
}
}
Alternatively I can store both Commands and Events in the same stream of base type Message
public abstract class EventSourcedSaga
{
protected EventSourcedSaga() { }
protected EventSourcedSaga(Identity id, IEnumerable<Message> messages)
{
Identity = id;
if (messages == null) throw new ArgumentNullException(nameof(messages));
var count = 0;
foreach (var message in messages)
{
var ev = message as Event;
var command = message as Command;
if(ev != null) Transition(ev);
else if(command != null) _messages.Add(command);
else throw new Exception($"Unsupported message type {message.GetType()}");
count++;
}
if (count == 0)
throw new ArgumentException("No messages provided");
// All we need to know is the original number of events this
// entity has had applied at time of construction.
_unmutatedVersion = count;
_constructing = false;
}
readonly IEventDispatchStrategy _dispatcher = new EventDispatchByReflectionStrategy("When");
readonly List<Message> _messages = new List<Message>();
readonly int _unmutatedVersion;
private readonly bool _constructing = true;
public readonly Identity Identity;
public IList<Message> GetMessages()
{
return _messages.ToArray();
}
public void Transition(Event e)
{
_messages.Add(e);
_dispatcher.Dispatch(this, e);
}
protected void SendCommand(Command c)
{
// Don't add a command whilst we are in the constructor. Message
// state transition during construction must not generate new
// commands, as those command will already be in the message list.
if (_constructing) return;
_messages.Add(c);
}
public int UnmutatedVersion() => _unmutatedVersion;
}
I believe the first two questions are the result of a wrong understanding of Process Managers (aka Sagas, see note on terminology at bottom).
Shift your thinking
It seems like you are trying to model it (as I once did) as an inverse aggregate. The problem with that: the "social contract" of an aggregate is that its inputs (commands) can change over time (because systems must be able to change over time), but its outputs (events) cannot. Once written, events are a matter of history and the system must always be able to handle them. With that condition in place, an aggregate can be reliably loaded from an immutable event stream.
If you try to just reverse the inputs and outputs as a process manager implementation, it's output cannot be a matter of record because commands can be deprecated and removed from the system over time. When you try to load a stream with a removed command, it will crash. Therefore a process manager modeled as an inverse aggregate could not be reliably reloaded from an immutable message stream. (Well I'm sure you could devise a way... but is it wise?)
So let's think about implementing a Process Manager by looking at what it replaces. Take for example an employee who manages a process like order fulfillment. The first thing you do for this user is setup a view in the UI for them to look at. The second thing you do is to make buttons in the UI for the user to perform actions in response to what they see on the view. Ex. "This row has PaymentFailed, so I click CancelOrder. This row has PaymentSucceeded and OrderItemOutOfStock, so I click ChangeToBackOrder. This order is Pending and 1 day old, so I click FlagOrderForReview"... and so forth. Once the decision process is well-defined and starts requiring too much of the user's time, you are tasked to automate this process. To automate it, everything else can stay the same (the view, even some of the UI so you can check on it), but the user has changed to be a piece of code.
"Go away or I will replace you with a very small shell script."
The process manager code now periodically reads the view and may issue commands if certain data conditions are present. Essentially, the simplest version of a Process Manager is some code that runs on a timer (e.g. every hour) and depends on particular view(s). That's the place where I would start... with stuff you already have (views/view updaters) and minimal additions (code that runs periodically). Even if you decide later that you need different capability for certain use cases, "Future You" will have a better idea of the specific shortcomings that need addressing.
And this is a great place to remind you of Gall's law and probably also YAGNI.
Any other reference material on the net for implementation of event sourced Sagas? Anything I can sanity check my ideas against?
Good material is hard to find as these concepts have very malleable implementations, and there are diverse examples, many of which are over-engineered for general purposes. However, here are some references that I have used in the answer.
DDD - Evolving Business Processes
DDD/CQRS Google Group (lots of reading material)
Note that the term Saga has a different implication than a Process Manager. A common saga implementation is basically a routing slip with each step and its corresponding failure compensation included on the slip. This depends on each receiver of the routing slip performing what is specified on the routing slip and successfully passing it on to the next hop or performing the failure compensation and routing backward. This may be a bit too optimistic when dealing with multiple systems managed by different groups, so process managers are often used instead. See this SO question for more information.
Typically, in "constructor" you subscribe to events with lambda-functions:
function Something(){
this.on('message', function(){ ... });
}
util.inherits(Something, events.EventEmitter);
This works well but extends bad. Methods play better with inheritance:
function Something(){
this.on('message', this._onMessage);
}
util.inherits(Something, events.EventEmitter);
Something.prototype._onMessage = function(){ ... };
What are the best practices to keep these event handler functions?
if i understood the question correctly then i think that it depends on how much open for changes you are willing to be.
your second example opens the option for subclasses (or, actually, any class) to override the handler's code, which isn't necessarily a good thing.
the first example prevents overriding but at the cost of having anonymous functions (sometimes containing a lot of code) inside your constructor. however, this code can be extracted to another private function (not on the prototype, just a regular function inside the module's file).
the open-close principal deals with this kind of questions.
(Pseudo-)Code
Here is a non-compilable code-sketch of the concepts I am having trouble with:
struct Data {};
struct A {};
struct B {};
struct C {};
/* and many many more...*/
template<typename T>
class Listener {
public:
Listener(MyObject* worker):worker(worker)
{ /* do some magic to register with RTI DDS */ };
public:
// This function is used ass a callback from RTI DDS, i.e. it will be
// called from other threads when new Data is available
void callBackFunction(Data d)
{
T t = extractFromData(d);
// Option 1: direct function call
// works somewhat, but shows "QObject::startTimer: timers cannot be started
// from another thread" at the console...
worker->doSomeWorkWithData(t); //
// Option 2: Use invokeMethod:
// seems to fail, as the macro expands including '"T"' and that type isn't
// registered with the QMetaType system...
// QMetaObject::invokeMethod(worker,"doSomeGraphicsWork",Qt::AutoConnection,
// Q_ARG(T, t)
// );
// Option 3: use signals slots
// fails as I can't make Listener, a template class, a QObject...
// emit workNeedsToBeDone(t);
}
private:
MyObject* worker;
T extractFromData(Data d){ return T(d);};
};
class MyObject : public QObject {
Q_OBJECT
public Q_SLOTS:
void doSomeWorkWithData(A a); // This one affects some QGraphicsItems.
void doSomeWorkWithData(B b){};
void doSomeWorkWithData(C c){};
public:
MyObject():QObject(nullptr){};
void init()
{
// listeners are not created in the constructor, but they should have the
// same thread affinity as the MyObject instance that creates them...
// (which in this example--and in my actual code--would be the main GUI
// thread...)
new Listener<A>(this);
new Listener<B>(this);
new Listener<C>(this);
};
};
main()
{
QApplication app;
/* plenty of stuff to set up RTI DDS and other things... */
auto myObject = new MyObject();
/* stuff resulting in the need to separate "construction" and "initialization" */
myObject.init();
return app.exec();
};
Some more details from the actual code:
The Listener in the example is a RTI DataReaderListener, the callback
function is onDataAvailable()
What I would like to accomplish
I am trying to write a little distributed program that uses RTI's Connext DDS for communication and Qt5 for the GUI stuff--however, I don't believe those details do matter much as the problem, as far as I understood it, boils down to the following:
I have a QObject-derived object myObject whose thread affinity might or might not be with the main GUI thread (but for simplicity, let's assume that is the case.)
I want that object to react to event's which happen in another, non-Qt 3rd-party library (in my example code above represented by the functions doSomeWorkWithData().
What I understand so far as to why this is problematic
Disclaimer: As usual, there is always more than one new thing one learns when starting a new project. For me, the new things here are/were RTI's Connext and (apparently) my first time where I myself have to deal with threads.
From reading about threading in Qt (1,2,3,4, and 5 ) it seems to me that
QObjects in general are not thread safe, i.e. I have to be a little careful about things
Using the right way of "communicating" with QObjects should allow me to avoid having to deal with mutexes etc myself, i.e. somebody else (Qt?) can take care of serializing access for me.
As a result from that, I can't simply have (random) calls to MyClass::doSomeWorkWithData() but I need to serialize that. One, presumably easy, way to do so is to post an event to the event queue myObject lives in which--when time is available--will trigger the execution of the desired method, MyClass::doSomeWorkWithData() in my case.
What I have tried to make things work
I have confirmed that myObject, when instantiated similarly as in the sample code above, is affiliated with the main GUI thread, i.e. myObject.thread() == QApplication::instance()->thread().
With that given, I have tried three options so far:
Option 1: Directly calling the function
This approach is based upon the fact that
- myObject lives in the GUI thread
- All the created listeners are also affiliated with the GUI thread as they are
created by `myObject' and inherit its thread that way
This actually results in the fact that doSomeWorkWithData() is executed. However,
some of those functions manipulate QGraphicsItems and whenever that is the case I get
error messages reading: "QObject::startTimer: timers cannot be started from another
thread".
Option 2: Posting an event via QMetaObject::invokeMethod()
Trying to circumvent this problem by properly posting an event for myObject, I
tried to mark MyObject::doSomeWorkWithData() with Q_INVOKABLE, but I failed at invoking the
method as I need to pass arguments with Q_ARG. I properly registered and declared my custom types
represented by struct A, etc. in the example), but I failed at the fact the
Q_ARG expanded to include a literal of the type of the argument, which in the
templated case didn't work ("T" isn't a registered or declared type).
Trying to use conventional signals and slots
This approach essentially directly failed at the fact that the QMeta system doesn't
work with templates, i.e. it seems to me that there simply can't be any templated QObjects.
What I would like help with
After spending about a week on attempting to fix this, reading up on threads (and uncovering some other issues in my code), I would really like to get this done right.
As such, I would really appreciate if :
somebody could show me a generic way of how a QObject's member function can be called via a callback function from another 3rd-party library (or anything else for that matter) from a different, non QThread-controlled, thread.
somebody could explain to me why Option 1 works if I simply don't create a GUI, i.e. do all the same work, just without a QGraphcisScene visualizing it (and the project's app being a QCoreApplication instead of a QApplication and all the graphics related work #defineed out).
Any, and I mean absolutely any, straw I could grasp on is truly appreciated.
Update
Based on the accepted answer I altered my code to deal with callbacks from other threads: I introduced a thread check at the beginning of my void doSomeWorkWithData() functions:
void doSomeWorkWithData(A a)
{
if( QThread::currentThread() != this->thread() )
{
QMetaObject::invokeMethod( this,"doSomeWorkWithData"
,Qt::QueuedConnection
,Q_ARG(A, a) );
return;
}
/* The actual work this function does would be below here... */
};
Some related thoughts:
I was contemplating to introduce a QMutexLocker before the if statement, but decided against it: the only part of the function that is potentially used in parallel (anything above the return; in the if statement) is--as far as I understand--thread safe.
Setting the connection type manually to Qt::QueuedConnection: technically, if I understand the documentation correctly, Qt should do the right thing and the default, Qt::AutoConnection, should end up becoming a Qt::QueuedConnection. But since would always be the case when that statement is reached, I decided to put explicitly in there to remind myself about why this is there.
putting the queuing code directly in the function and not hiding it in an interim function: I could have opted to put the call to invokeMethod in another interim function, say queueDoSomeWorkWithData()', which would be called by the callback in the listener and then usesinvokeMethodwith anQt::AutoConnection' on doSomeWorkWithData(). I decided against this as there seems no way for me to auto-code this interim function via templates (templates and the Meta system was part of the original problem), so "the user" of my code (i.e. the person who implements doSomeWorkWithData(XYZ xyz)) would have to hand type the interim function as well (as that is how the templated type names are correctly resolved). Including the check in the actual function seems to me to safe typing an extra function header, keeps the MyClass interface a little cleaner, and better reminds readers of doSomeWorkWithData() that there might be a threading issue lurking in the dark.
It is ok to call a public function on a subclass of QObject from another thread if you know for certain that the individual function will perform only thread-safe actions.
One nice thing about Qt is that it will handle foreign threads just as well as it handles QThreads. So, one option is to create a threadSafeDoSomeWorkWithData function for each doSomeWorkWithData that does nothing but QMetaMethod::invoke the non-threadsafe one.
public:
void threadSafeDoSomeWorkWithData(A a) {
QMetaMethod::invoke("doSomeWorkWithData", Q_ARG(A,a));
}
Q_INVOKABLE void doSomeWorkWithData(A a);
Alternatively, Sergey Tachenov suggests an interesting way of doing more or less the same thing in his answer here. He combines the two functions I suggested into one.
void Obj2::ping() {
if (QThread::currentThread() != this->thread()) {
// not sure how efficient it is
QMetaObject::invoke(this, "ping", Qt::QueuedConnection);
return;
}
// thread unsafe code goes here
}
As to why you see normal behaviour when not creating a GUI? Perhaps you're not doing anything else that is unsafe, aside from manipulating GUI objects. Or, perhaps they're the only place in which your thread-safety problems are obvious.
So I'm trying to use the TPL features in .NET 4.0 and have some code like this (don't laugh):
/// <summary>Fetches a thread along with its posts. Increments the thread viewed counter.</summary>
public Thread ViewThread(int threadId)
{
// Get the thread along with the posts
Thread thread = this.Context.Threads.Include(t => t.Posts)
.FirstOrDefault(t => t.ThreadID == threadId);
// Increment viewed counter
thread.NumViews++;
Task.Factory.StartNew(() =>
{
try {
this.Context.SaveChanges();
}
catch (Exception ex) {
this.Logger.Error("Error viewing thread " + thread.Title, ex);
}
this.Logger.DebugFormat(#"Thread ""{0}"" viewed and incremented.", thread.Title);
});
return thread;
}
So my immediate concerns with the lambda are this.Context (my entity framework datacontext member), this.Logger (logger member) and thread (used in the logger call). Normally in the QueueUserWorkItem() days, I would think these would need to be passed into the delegate as part of a state object. Are closures going to be bail me out of needing to do that?
Another issue is that the type that this routine is in implements IDisposable and thus is in a using statement. So if I do something like...
using (var bl = new ThreadBL()) {
t = bl.ViewThread(threadId);
}
... am I going to create a race between a dispose() call and the TPL getting around to invoking my lambda?
Currently I'm seeing the context save the data back to my database but no logging - no exceptions either. This could be a configuration thing on my part but something about this code feels odd. I don't want to have unhandled exceptions in other threads. Any input is welcome!
As for your question on closures, yes this is exactly what closures are about. You don't worry about passing state, instead it is captured for you from any outer context and copied onto a compiler supplied class which is also where the closure method will be defined. The compiler does a lot of magic here to make you're life simple. If you want to understand more I highly recommend picking up Jon Skeet's C# in Depth. The chapter on closures is actually available here.
As for your specific implementation, it will not work mainly for the exact problem you mentioned: the Task will be scheduled at the end of ViewThread, but potentially not execute before your ThreadBL instance is disposed of.