我以前有過這種問題,通過從自定義類中引發的事件更新GUI元素,但我可以用類似的東西繞過它:線程之間傳遞對象會導致異常,因爲不同的線程擁有它
MyTextBlock.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
(Action)(() => { LoggingTextBlock.Text += Message += "\r\n"; }));
我認爲這個問題對於UI線程是唯一的,但顯然它適用於所有線程。不幸的是,我的自定義類沒有像UIElements那樣調用.Dispatcher()例程。那麼你應該如何將對象傳遞給其他線程並讓它們能夠使用它們?
例如,我有一個基本偵聽器類,其主要工作基本上是查找一些數據,引發事件並傳遞該數據。以下是數據類的部分,我想經過:
// Just the class for carrying the job data.
public class JobData
{
// NOTE: I don't no have trouble accessing these properties from a
// different thread
public string SomeProperty1 { get; set; }
public string SomeProperty2 { get; set; }
public string SomeProperty3 { get; set; }
// ...
// more properties
// ...
// This a .NET object of type System.Printing.PrintSystemJobInfo. This
// is the guy that gives me trouble. Later on, I can't access members
// of Job without getting the "The calling thread cannot access this
// object because a different thread owns it" error.
PrintSystemJobInfo m_Job = null;
public PrintSystemJobInfo Job
{
get
{
if (m_Job == null)
{ throw new ArgumentNullException(); }
return m_Job;
}
set { m_Job = value; }
}
}
以下是在一個線程中運行的類的部分,收集數據,並觸發事件來傳遞數據給關有人在傾聽。
// Thread who monitors looking for data to package into JobData and send
// to any listeners.
public class JobMonitor
{
public delegate void NewJobEvent(JobData jobStuff);
public event NewJobEvent NewJob;
// Call this when you have some job data and need to notify listeners
private void OnNewJob(object newJobData)
{
JobData newJobData = (JobData)newJobData;
if (NewJob != null)
{
NewJob(newJobData);
}
}
private void WorkerRoutine()
{
while(true)
{
// Wait for data
// ...
// ...
// when data is found
JobData myJobData = new JobData();
myJobData.SomeProperty1 = "some data";
myJobData.SomeProperty2 = "some data";
int jobID = GetCurrentJobID();
string printerName = GetCurrentPrinterName();
// .NET class System.Printing.PrintQueue
PrintQueue printQueue = new PrintQueue(new PrintServer(), printerName);
PrintSystemJobInfo jobInfo = null;
jobInfo = printQueue.GetJob(jobID);
// This is the guy in my JobData class that I'll have trouble accessing
// later on.
myJobData.Job = jobInfo;
// Time to fire off the event
OnNewJob(myJobData);
}
}
}
以下是實例化JobMonitor類並捕獲其事件的類的一部分。它無法訪問JobMonitor的其中一個屬性。
// This class signs up to recieve and process events from the JobMonitor class.
public class JobProcessor
{
// this is the method that handles the incoming job events. This is where
// i have trouble.
private void NewJobEventHandler(JobData newJob)
{
string temp = newJob.SomeProperty1; // this works fine
bool bTemp = newJob.Job.IsPaused; // this throws an exception "The
// calling read cannot access this
// object because a different thread
// owns it"
}
private JobMonitor m_monitor = null;
public JobProcessor()
{
m_monitor = new JobMonitor();
//attaches a method to handle incoming job events.
m_monitor.NewJob += new JobMonitor.NewJobEvent(NewJobEventHandler);
m_monitor.Start();
}
}
所以JobProcessor.NewJobEventHandler()方法是在那裏我得到的例外「因爲不同的線程擁有它調用線程不能訪問該對象」。我需要能夠訪問此屬性和下面的屬性和方法。我需要做什麼才能訪問我需要的內容?
嗯,我等了一會兒,看看是否還有其他建議可能出現。 「SyncronizationContext」方法對我來說並沒有結果。我對這個概念有點遺憾,所以我很可能做錯了。幸運的是,檢索PrintSystemJobInfo對象很容易,並且有足夠的信息可供我的目標線程自行獲取此對象。理想情況下,我不必這樣做,我的目標線程不需要知道如何獲取這些信息。哦,對我來說,放眼未來它並不是一個妥協。 – Ultratrunks