線程切換
回答
沒有靈丹妙藥,這將允許一個線程啓動委託執行到另一個線程。目標線程必須特別構造以允許這樣做。在UI線程的情況下,有一個消息泵來分派和處理消息。該消息泵可用於通過接口執行編組操作。
ISynchronizeInvoke target = someForm; // where someForm is a Form or Control
target.Invoke(
(Action)(() =>
{
MessageBox.Show("I am on the target thread");
}), null);
在你的情況下,線程調用異步函數必須具有某種內置到它的生產者 - 消費者的機制來獲得一個回調到該線程異步執行其已經被指示從輔助線程這樣做後, 。不幸的是,這不是一個可以解決的小問題。
這裏是你可以創建一個線程,可以接受委託執行的一個途徑。
public class SynchronizeInvokeThread : ISynchronizeInvoke
{
private Thread m_Thread;
private BlockingCollection<WorkItem> m_Collection = new BlockingCollection<WorkItem>();
public SynchronizeInvokeThread()
{
m_Thread = new Thread(
() =>
{
SynchronizationContext.SetSynchronizationContext(new MySynchronizationContext(this));
while (true)
{
WorkItem wi = m_Collection.Take();
wi.Complete(wi.Method.DynamicInvoke(wi.Args));
}
});
m_Thread.Start();
}
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
var wi = new WorkItem(method, args);
m_Collection.Add(wi);
return wi;
}
public object EndInvoke(IAsyncResult result)
{
var wi = (WorkItem)result;
wi.AsyncWaitHandle.WaitOne();
return wi.Result;
}
public object Invoke(Delegate method, object[] args)
{
var wi = new WorkItem(method, args);
m_Collection.Add(wi);
wi.AsyncWaitHandle.WaitOne();
return wi.Result;
}
public bool InvokeRequired
{
get { return Thread.CurrentThread != m_Thread; }
}
private class MySynchronizationContext : SynchronizationContext
{
private ISynchronizeInvoke m_SynchronizingObject;
public MySynchronizationContext(ISynchronizeInvoke synchronizingObject)
{
m_SynchronizingObject = synchronizingObject;
}
public override void Post(SendOrPostCallback d, object state)
{
m_SynchronizingObject.BeginInvoke(d, new object[] { state });
}
public override void Send(SendOrPostCallback d, object state)
{
m_SynchronizingObject.Invoke(d, new object[] { state });
}
}
private class WorkItem : IAsyncResult
{
private Delegate m_Method;
private object[] m_Args;
private object m_Result = null;
private ManualResetEvent m_Signal = new ManualResetEvent(false);
public WorkItem(Delegate method, object[] args)
{
m_Method = method;
m_Args = args;
}
public void Complete(object result)
{
m_Result = result;
m_Signal.Set();
}
public object Result
{
get { return m_Result; }
}
public Delegate Method
{
get { return m_Method; }
}
public object[] Args
{
get { return m_Args; }
}
public object AsyncState
{
get { return null; }
}
public WaitHandle AsyncWaitHandle
{
get { return m_Signal; }
}
public bool CompletedSynchronously
{
get { return false; }
}
public bool IsCompleted
{
get { return m_Signal.WaitOne(0); }
}
}
}
它可以像這樣使用。
ISynchronizeInvoke target = new SynchronizeInvokeThread();
target.Invoke(
(Action)(() =>
{
Console.WriteLine("I am on the target thread");
SynchronizationContext.Current.Post(
(state) =>
{
Console.WriteLine("I even have a synchronization context!");
}, null);
}), null);
更新:
每低於BlockingCollection
評論僅在.NET 4.0或爲Reactive Extensions下載的一部分提供。如果這個數據結構不適合你,那麼這個已經很難的代碼變得更加困難。
使用一個BackgroundWorker。回調將在自己的線程上。
如果即使在回調之後異步操作仍需要運行,您可以使用WPF System.Windows.Application.Current.Dispatcher.Invoke/BeginInvoke進行多個回調,或者如果可以使用WinForms窗體或控件實例本身並調用Invoke/BeginInvoke。
如果它是一個控制檯應用程序,然後的BackgroundWorker的完成事件被稱爲在不同的線程。在我們呼籲RunAsync fnction .. – dinesh
像Brian Gideon
提到你應該使用ISynchronizeInvoke「System.ComponentModel.ISynchronizeInvoke」。在你希望在另一個線程上封送其線程執行的類上實現它。這裏的示例Media
類「我實現的一些類與Com對象進行交互,因此它應該在主線程中執行它的方法」;由於類實現它使用System.Threading.SynchronizationContext.Current
,因此您可以在WindowsForms中使用它,但不是控制檯應用程序,因爲System.Threading.SynchronizationContext.Current爲空。
無論何時您想將此類的執行編組到創建它的線程時,只需調用其Invoke
方法即可。
public abstract class Media : ISynchronizeInvoke
{
//....
private readonly System.Threading.SynchronizationContext _currentContext = System.Threading.SynchronizationContext.Current;
private readonly System.Threading.Thread _mainThread = System.Threading.Thread.CurrentThread;
private readonly object _invokeLocker = new object();
//....
#region ISynchronizeInvoke Members
public bool InvokeRequired
{
get
{
return System.Threading.Thread.CurrentThread.ManagedThreadId != this._mainThread.ManagedThreadId;
}
}
/// <summary>
/// This method is not supported!
/// </summary>
/// <param name="method"></param>
/// <param name="args"></param>
/// <returns></returns>
[Obsolete("This method is not supported!", true)]
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
throw new NotSupportedException("The method or operation is not implemented.");
}
/// <summary>
/// This method is not supported!
/// </summary>
/// <param name="method"></param>
/// <param name="args"></param>
/// <returns></returns>
[Obsolete("This method is not supported!", true)]
public object EndInvoke(IAsyncResult result)
{
throw new NotSupportedException("The method or operation is not implemented.");
}
public object Invoke(Delegate method, object[] args)
{
if (method == null)
{
throw new ArgumentNullException("method");
}
lock (_invokeLocker)
{
object objectToGet = null;
SendOrPostCallback invoker = new SendOrPostCallback(
delegate(object data)
{
objectToGet = method.DynamicInvoke(args);
});
_currentContext.Send(new SendOrPostCallback(invoker), method.Target);
return objectToGet;
}
}
public object Invoke(Delegate method)
{
return Invoke(method, null);
}
#endregion//ISynchronizeInvoke Members
}
- 1. 切換線程
- 2. 線程切換
- 3. ASP.NET線程切換
- 4. Java線程切換
- 5. RxJava線程切換
- 6. 多線程線程切換問題
- 7. PyDbg中的線程切換
- 8. 如何切換線程
- 9. Java - 切換回主線程?
- 10. serialport timeoutexception線程切換
- 11. Android:切換(ToggleButton)和線程
- 12. 線程上下文切換vs進程上下文切換
- 13. TabBarController切換視圖[切換到線程12803]
- 14. java線程之間的切換控制
- 15. 強制線程上下文切換
- 16. 上下文切換多線程
- 17. 切換線程中的Rx鏈多次
- 18. 強制GIL不要切換線程
- 19. 如何防止線程切換?
- 20. Java多線程時間切換
- 21. 在線程切換時暫停gdb
- 22. 使用GtkAda進行Ada線程切換
- 23. 切換回ReactiveCocoa的主線程
- 24. 多線程:上下文切換
- 25. 使用SIGALRM切換線程上下文
- 26. Android - 從UI線程切換回來?
- 27. Python切換線程的頻率如何?
- 28. 線程和上下文切換C++
- 29. 線程之間的上下文切換
- 30. Eclipse - 調試線程執行時惱人的線程切換
有什麼樣? – dinesh
我更新了我的答案。 –
@Brain Gideon:使用'CustomThread'不會調用目標線程中的代碼。這是因爲你不使用'SynchronizationContext' ...來證明它。在Windows窗體上運行一個測試,並用'textBox1.Text =「一些數據」替換'Console.WriteLine';''你將有一個交叉線程異常..另外請注意,您正在使用'ConcurrentCollection',問題標籤是C#3.0' –