SendOrPostCallback xxx = vg => { Text ="内部: "+vg.ToString(); };
dynamic vx = new { a = SynchronizationContext.Current, b = xxx };
Thread td = new Thread(x =>
{
dynamic tmp = x;
// SynchronizationContext ds = x as SynchronizationContext;
for (int i = 0; i < 500; i++)
{
System.Threading.Thread.Sleep(10);
//((SynchronizationContext)tmp.a).Post(v => { Text = v.ToString(); }, i + " " + DateTime.Now);
((SynchronizationContext)tmp.a).Post(tmp.b, i + " " + DateTime.Now);
}
// this.Invoke((MethodInvoker)delegate { MessageBox.Show("ok"); });
});
td.Start(vx);
void uiexe(object cs)
{
Text = cs.ToString();
}
//ThreadPool.QueueUserWorkItem(x =>
//{
// for (int i = 0; i < 100; i++)
// {
// System.Threading.Thread.Sleep(10);
// ((SynchronizationContext)x).Post(y => { Text = i + " " + DateTime.Now; }, null);
// }
//}, SynchronizationContext.Current);
SynchronizationContext nb = SynchronizationContext.Current;
ThreadPool.QueueUserWorkItem(x =>
{
for (int i = 0; i < 100; i++)
{
System.Threading.Thread.Sleep(10);
nb.Post(y => { Text = i + " " + DateTime.Now; }, null);
}
}, null);
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// let's check the context here
var context = SynchronizationContext.Current;
if (context == null)
MessageBox.Show("No context for this thread");
else
MessageBox.Show("We got a context");
// create a form
Form1 form = new Form1();
// let's check it again after creating a form
context = SynchronizationContext.Current;
if (context == null)
MessageBox.Show("No context for this thread");
else
MessageBox.Show("We got a context");
if (context == null)
MessageBox.Show("No context for this thread");
Application.Run(new Form1());
}
而且它使用非常方便,只需要关注下面两个方法即可:
1. Send:发送界面更新请求至主线程,阻塞当前线程直至返回。
2. Post:发送界面更新请求至主线程,不阻塞当前线程。
实际上,他们都是同一个方法,只是 send 是同步,post 是异步
这是一个很简单的例子,也许看过的人都会说:根本就没有摆脱Control 和 From 啊!
诚然如此,为了摆脱Control,我们还需要封装一下,看下面的BackgroundWorker 类:
class BackgroundWorker
{
public EventHandler<EventArgs> WorkerStarted;
public EventHandler<ProgressEventArgs> ReportProgress;
public EventHandler<EventArgs> WorkerCompleted;
public SynchronizationContext Context { get; set; }
public void Start()
{
Thread t = new Thread(() =>
{
Context.Post(SetStartState, null);
for (int i = 0; i <= 10; i++)
{
Thread.Sleep(new TimeSpan(0, 0, 1));
Context.Post(UpdateProgress, i * 10);
}
Thread.Sleep(new TimeSpan(0, 0, 1));
Context.Post(SetCompletedState, null);
}
);
t.Start();
}
private void SetStartState(object state)
{
if (WorkerStarted != null)
{
WorkerStarted(this, new EventArgs());
}
}
private void SetCompletedState(object state)
{
if (WorkerCompleted != null)
{
WorkerCompleted(this, new EventArgs());
}
}
private void UpdateProgress(object state)
{
if (ReportProgress != null)
{
ReportProgress(this, new ProgressEventArgs {Progress = Convert.ToInt32(state)});
}
}
}
有两个特别的地方:
1. 构造的时候,需要提供SynchronizationContext 实例
2. 它的三个事件(WorkerStarted,ReportProgress, WorkerCompleted),都是在 post 方法里面触发的。这样做就可以确保事件的订阅方法脱离后台线程,进入主线程。
protected override void OnLoad(EventArgs e)
{
_context = SynchronizationContext.Current;
}
private void btnWrapper_Click(object sender, EventArgs e)
{
btnWrapper.Enabled = false;
BackgroundWorker worker = new BackgroundWorker {Context = SynchronizationContext.Current};
worker.WorkerStarted += (o, args) => { txtWrapper.Text = "Running background thread..."; };
worker.ReportProgress += (o, args) => { txtWrapper.Text = string.Format("Progress: {0}", args.Progress); };
worker.WorkerCompleted += (o, args) =>
{
txtWrapper.Text = "Background thread completed";
btnWrapper.Enabled = true;
};
worker.Start();
}
WebChannelFactory<JK.IXX> dd = new WebChannelFactory<JK.IXX>(new Uri("http://localhost/xxii"));
// ChannelFactory<JK.IXX> dd = new ChannelFactory<JK.IXX>(bd, "http://localhost/xxii");
// dd.Endpoint.Behaviors.Add(new WebHttpBehavior());
// WebOperationContext.Current.IncomingRequest.Headers.Add("dddd","ssss");
dd.Endpoint.Behaviors.Add(new XEndpointBehavior());
//SynchronizationContext.Current.Post(
// SynchronizationContext
JK.IXX service = dd.CreateChannel();
IClientChannel clientchanel = service as IClientChannel;
//IServiceChannel
using (OperationContextScope scope = new OperationContextScope(clientchanel))
{
var xddd = WebOperationContext.Current;
xddd.OutgoingRequest.Headers.Add("ssss", "dddd" + DateTime.Now);
//加不了
//*****************************************************************************************
//using (OperationContextScope scope = new OperationContextScope(iContextChannel))
//{
//MessageHeader<string> mh = new MessageHeader<string>("abcde");
//MessageHeader header = mh.GetUntypedHeader("AuthKey", http://www.cjb.com/);
//OperationContext.Current.OutgoingMessageHeaders.Add(header);
//return func();
//}
//服务端:
//string authKey = string.Empty;
//if (OperationContext.Current != null)
//{
//authKey = OperationContext.Current.IncomingMessageHeaders.GetHeader<string>("AuthKey", http://www.cjb.com);
//}
//*****************************************************************************************
//调用方法获取消息头
string messHeader = service.getstr();
MessageBox.Show(messHeader);
Console.WriteLine(messHeader);
Console.WriteLine("服务方法已调用");
}