Gia*_*vas 10 c# multithreading design-patterns command-pattern
有一个扩展的命令模式实现,以支持C#中的多命令(组):
var ctx= //the context object I am sharing...
var commandGroup1 = new MultiItemCommand(ctx, new List<ICommand>
{
new Command1(ctx),
new Command2(ctx)
});
var commandGroup2 = new MultiItemCommand(ctx, new List<ICommand>
{
new Command3(ctx),
new Command4(ctx)
});
var groups = new MultiCommand(new List<ICommand>
{
commandGroup1 ,
commandGroup2
}, null);
Run Code Online (Sandbox Code Playgroud)
现在,执行就像:
groups.Execute();
Run Code Online (Sandbox Code Playgroud)
我正在共享相同的上下文(ctx)对象.
Web应用程序的执行计划需要在不同的线程中分离
commandGroup1和commandGroup2分组.具体来说,commandGroup2将在新线程和commandGroup1主线程中执行.
执行现在看起来像:
//In Main Thread
commandGroup1.Execute();
//In the new Thread
commandGroup2.Execute();
Run Code Online (Sandbox Code Playgroud)
如何线程安全地共享相同的内容context object (ctx),以便能够commandGroup1从新线程回滚?
是否 t.Start(ctx);足够或我必须使用锁或什么?
一些代码实现示例在这里
假设我们有一个 MultiCommand 类,它聚合了 ICommand 列表,并且有时必须异步执行所有命令。所有命令必须共享上下文。每个命令都可以更改上下文状态,但没有固定的顺序!
第一步是启动 CTX 中传递的所有 ICommand 执行方法。下一步是为新的 CTX 更改设置事件侦听器。
public class MultiCommand
{
private System.Collections.Generic.List<ICommand> list;
public List<ICommand> Commands { get { return list; } }
public CommandContext SharedContext { get; set; }
public MultiCommand() { }
public MultiCommand(System.Collections.Generic.List<ICommand> list)
{
this.list = list;
//Hook up listener for new Command CTX from other tasks
XEvents.CommandCTX += OnCommandCTX;
}
private void OnCommandCTX(object sender, CommandContext e)
{
//Some other task finished, update SharedContext
SharedContext = e;
}
public MultiCommand Add(ICommand cc)
{
list.Add(cc);
return this;
}
internal void Execute()
{
list.ForEach(cmd =>
{
cmd.Execute(SharedContext);
});
}
public static MultiCommand New()
{
return new MultiCommand();
}
}
Run Code Online (Sandbox Code Playgroud)
每个命令处理异步部分类似于:
internal class Command1 : ICommand
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
throw new NotImplementedException();
}
public async void Execute(object parameter)
{
var ctx = (CommandContext)parameter;
var newCTX = await Task<CommandContext>.Run(() => {
//the command context is here running in it's own independent Task
//Any changes here are only known here, unless we return the changes using a 'closure'
//the closure is this code - var newCTX = await Task<CommandContext>Run
//newCTX is said to be 'closing' over the task results
ctx.Data = GetNewData();
return ctx;
});
newCTX.NotifyNewCommmandContext();
}
private RequiredData GetNewData()
{
throw new NotImplementedException();
}
}
Run Code Online (Sandbox Code Playgroud)
最后我们建立了一个通用的事件处理程序和通知系统。
public static class XEvents
{
public static EventHandler<CommandContext> CommandCTX { get; set; }
public static void NotifyNewCommmandContext(this CommandContext ctx, [CallerMemberName] string caller = "")
{
if (CommandCTX != null) CommandCTX(caller, ctx);
}
}
Run Code Online (Sandbox Code Playgroud)
每个命令的执行函数中都可以进行进一步的抽象。但我们现在不讨论这个。
以下是此设计的作用和不作用:
如果您需要并发性,那么这意味着上下文状态很重要,该设计与此类似但有所不同。使用闭包函数和回调可以轻松实现该设计。
| 归档时间: |
|
| 查看次数: |
1106 次 |
| 最近记录: |