只是 Control 控件 Invoke 和 BeginInvoke 呼叫的函数。 private Object MarshaledInvoke(Control caller, Delegate method, Object[] args, bool synchronous) { // Marshaling an invoke occurs in three steps: // // 1. Create a ThreadMethodEntry that contains the packet of information // about this invoke. This TME is placed on a linked list of entries because // we have a gap between the time we PostMessage and the time it actually // gets processed, and this gap may allow other invokes to come in. Access // to this linked list is always synchronized. // // 2. Post ourselves a message. Our caller has already determined the // best control to call us on, and we should almost always have a handle. // // 3. If we're synchronous, wait for the message to get processed. We don't do // a SendMessage here so we're compatible with OLE, which will abort many // types of calls if we're within a SendMessage. // if (!IsHandleCreated) { throw new InvalidOperationException(SR.GetString(SR.ErrorNoMarshalingThread)); } // We have to demand unmanaged code permission here for the control hosted in // the browser case. Without this
// We don't want to wait if we're on the same thread, or else we'll deadlock. // It is important that syncSameThread always be false for asynchronous calls. // bool syncSameThread = false; int pid; // ignored if (SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, Handle), out pid) == SafeNativeMethods.GetCurrentThreadId()) { if (synchronous) syncSameThread = true; } // Store the compressed stack information from the thread that is calling the Invoke() // so we can assign the same security context to the thread that will actually execute // the delegate being passed. // ExecutionContext executionContext = null; if (!syncSameThread) { executionContext = ExecutionContext.Capture(); } ThreadMethodEntry tme = new ThreadMethodEntry(caller, method, args, synchronous, executionContext);
lock (this) { if (threadCallbackList == null) { threadCallbackList = new Queue(); } }
怎么才子线程里 调用主线程执行ParameterizedThreadStart或者ThreadStart
在我不知道的情况下怎么调用Invoke,
所以我想知道怎么直接调用主线程来执行指定的委托就是说有2个线程 主线程,子线程
怎么才子线程里 调用主线程执行ParameterizedThreadStart或者ThreadStart
不知道是不是这样.
然后使用这个作为桥梁去 Dispatcher。其实,如果你在非 UI 线程中没有使用 UI 控件,为什么要 Invoke 呢?
算了 我就说下我的需求好了我现在有一个线程队列.可以自由加入线程,当然会加入怎么样的线程委托就不知道了
OK那么现在这个队列开始运行了....
可是在运行过程中发现有一个委托抛出异常..不允许跨线程控制控件
so~~
说明这个线程中,有一个地方设置了某个控件的值好吧,我现在再次尝试用主线程调用这个委托....(这个地方就写不来了....)over了
怎么才子线程里 调用主线程执行ParameterizedThreadStart或者ThreadStart我觉得这个必须主线程执行
可以设置个Mutex或者其他类似的东西。
主线程等待,子线程给信号
你如果不知道那个窗体的哪个控件导致的异常,就很难了。
C#能不能向VC++一样把窗口句柄或指针作为参数传到线程里,在线程中还能还原出这个窗口对象?
这个队列只是管理线程的 线程里不一定会有form或者别的控件啊
怎么能让调用的人一定要传送呢?
再说调用的人可能也是接受其他地方传过来的委托,,所以传form是不现实的
其实我的意思就是说 C#中有没有这样的方法 知道某个线程的id 能不能传送一个委托让这个线程运行
调用这两个东西本来就不应该在什么窗口线程中去调用。首先这个要明确,否则你就会去跑到窗体线程上去“排队”去了,而不是真正去使用多线程去处理数据。只有当处理数据完成之后,需要在窗体上的控件显示结果时,才需要调用这个控件的Invoke。这时候你自己应该知道该是哪一个窗体(控件)。例如最次地,它可能是 ApplciationContext.MainForm。
你这可能还是函数式思维习惯,以为什么都是“调用函数、得到返回值、在用返回值调用下一个函数....”。多线程编程,就是在调用一个方法时将它需要的参数(你这里就是将来要显示的控件)作为参数传递给它。如果不预先传递给它,那么你就只能得到阻塞式的所谓多线程程序(假的多线程程序),也就是产生线程的过程要等到所谓的线程执行之后再“取得”结果再来决定显示到哪里,这就不是多线程编程的正确思维。多线程编程就是要预先传送form,然后一旦产生线程之后就不管之后的逻辑了(交给线程程序去处理之后的逻辑了)。否则就是函数式思维方式了。
Thread中有一个很大的while不断执行推送到MessageQueue中的Code Block,现在Invoke就是将block加入到MQ中
换个角度考虑问题
sendmessage or postmessage
2 使用BeginInvoke 等价API PostMessage
3 设置CheckForIllegalCrossThreadCalls = false
少年,多线程的每个线程应该是独立的,可重用的,如果依赖Form,那只能说是伪多线程,因为必定要用到主线程来更改Form信息。再说一下红字,是的线程里不一定有form或者别的控件,可是到时候万一有了,你要怎么办,重新写还是大改?
你又说:“我知道需要调度,但是Invoke的弊端就是必须要知道form或者control
在我不知道的情况下怎么调用Invoke”。这个委托内部去设置的那个控件本身,对委托编写者来说不是知道的吗?他写委托的时候为什么不能Invoke回调去设置控件的值呢?
在窗体构造方法中加入下一行代码:System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;当非创建这个控件的线程访问、修改这个控件可能会导致不可预知的后果。所以不推荐跨线程访问控件。
也就是说系统的Invoke 就是用SendMessage来实现的喽?
//
// 1. Create a ThreadMethodEntry that contains the packet of information
// about this invoke. This TME is placed on a linked list of entries because
// we have a gap between the time we PostMessage and the time it actually
// gets processed, and this gap may allow other invokes to come in. Access
// to this linked list is always synchronized.
//
// 2. Post ourselves a message. Our caller has already determined the
// best control to call us on, and we should almost always have a handle.
//
// 3. If we're synchronous, wait for the message to get processed. We don't do
// a SendMessage here so we're compatible with OLE, which will abort many
// types of calls if we're within a SendMessage.
// if (!IsHandleCreated) {
throw new InvalidOperationException(SR.GetString(SR.ErrorNoMarshalingThread));
} // We have to demand unmanaged code permission here for the control hosted in
// the browser case. Without this
ActiveXImpl activeXImpl = (ActiveXImpl)Properties.GetObject(PropActiveXImpl);
if (activeXImpl != null) {
IntSecurity.UnmanagedCode.Demand();
}
// We don't want to wait if we're on the same thread, or else we'll deadlock.
// It is important that syncSameThread always be false for asynchronous calls.
//
bool syncSameThread = false;
int pid; // ignored
if (SafeNativeMethods.GetWindowThreadProcessId(new HandleRef(this, Handle), out pid) == SafeNativeMethods.GetCurrentThreadId()) {
if (synchronous)
syncSameThread = true;
} // Store the compressed stack information from the thread that is calling the Invoke()
// so we can assign the same security context to the thread that will actually execute
// the delegate being passed.
//
ExecutionContext executionContext = null;
if (!syncSameThread) {
executionContext = ExecutionContext.Capture();
}
ThreadMethodEntry tme = new ThreadMethodEntry(caller, method, args, synchronous, executionContext);
lock (this) {
if (threadCallbackList == null) {
threadCallbackList = new Queue();
}
}
lock (threadCallbackList) {
if (threadCallbackMessage == 0) {
threadCallbackMessage = SafeNativeMethods.RegisterWindowMessage(Application.WindowMessagesVersion + "_ThreadCallbackMessage");
}
threadCallbackList.Enqueue(tme);
}
if (syncSameThread) {
InvokeMarshaledCallbacks();
} else {
//
UnsafeNativeMethods.PostMessage(new HandleRef(this, Handle), threadCallbackMessage, IntPtr.Zero, IntPtr.Zero);
} if (synchronous) {
if (!tme.IsCompleted) {
WaitForWaitHandle(tme.AsyncWaitHandle);
}
if (tme.exception != null) {
throw tme.exception;
}
return tme.retVal;
}
else {
return(IAsyncResult)tme;
}
}