我是TPL和WPf的新手,並且存在以下問題。 我嘗試下載一個無限循環的站點(這裏只有一個for循環),並且 將它添加到隊列中。下一個任務將其取出並顯示在文本塊中。 但是我似乎沒有得到正確的線程爲用戶界面,但我認爲我正確使用TaskScheduler。WPF,TPL,生產者/消費者模式 - 錯誤線程錯誤
謝謝你的幫助!
BlockingCollection<string> blockingCollection = new BlockingCollection<string>();
CancellationToken token = tokenSource.Token;
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task task1 = new Task(
(obj) =>
{
for (int i = 0; i < 10; i++)
{
if (token.IsCancellationRequested)
{
TxtBlock2.Text = "Task cancel detected";
throw new OperationCanceledException(token);
}
else
{
string code = i.ToString() + "\t" + AsyncHttpReq.get_source_WebRequest(uri);
blockingCollection.Add(code);
}
}
}, TaskScheduler.Default);
task1.ContinueWith(antecedents =>
{
TxtBlock2.Text = "Signalling production end";
blockingCollection.CompleteAdding();
}, uiScheduler);
Task taskCP = new Task(
(obj) =>
{
while (!blockingCollection.IsCompleted)
{
string dlCode;
if (blockingCollection.TryTake(out dlCode))
{
//the calling thread cannot access this object because a different thread owns it.
TxtBlock3.Text = dlCode;
}
}
}, uiScheduler);
WindowsBase.dll!System.Windows.Threading.Dispatcher.VerifyAccess() + 0x4a bytes
WindowsBase.dll!System.Windows.DependencyObject.SetValue(System.Windows.DependencyProperty dp, object value) + 0x19 bytes
PresentationFramework.dll!System.Windows.Controls.TextBlock.Text.set(string value) + 0x24 bytes
WpfRibbonApplication4.exe!WpfRibbonApplication4.MainWindow.Button1_Click.AnonymousMethod__4(obj對象)線83個+ 0x16字節C# mscorlib.dll中!System.Threading.Tasks.Task.InnerInvoke()+ 0×44字節 mscorlib.dll!System.Threading.Tasks.Task.Execute()+ 0x43 bytes mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj)+ 0x27 bytes
mscorlib.dll!System.Threading.ExecutionContext .Run(System.Threading.ExecutionContext executionContext,System.Threading.ContextCallback回調,對象狀態,布爾ignoreSyncCtx)+ 0xb0字節
mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot)+ 0x154 bytes
mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution)+ 0x8b字節
mscorlib.dll中!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()+ 0x7的字節 mscorlib.dll中!System.Threading.ThreadPoolWorkQueue.Dispatch()+ 0x147字節
mscorlib.dll中! System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()+ 0x2d字節
[原產於託管過渡]
System.InvalidOperationException was unhandled by user code
Message=The calling thread cannot access this object because a different thread owns it.
Source=WindowsBase
StackTrace:
at System.Windows.Threading.Dispatcher.VerifyAccess()
at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value)
at System.Windows.Controls.TextBlock.set_Text(String value)
at WpfRibbonApplication4.MainWindow.<>c__DisplayClass5.<Button1_Click>b__3(Object o) in C:\ ... \WpfRibbonApplication4\WpfRibbonApplication4\MainWindow.xaml.cs:line 90
at System.Threading.Tasks.Task.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
InnerException:
非常感謝您的幫助。 我仍然有兩個問題: 我用Task.Factory.StartNew重寫了我的代碼。但是,我的任務2似乎會導致問題。沒有錯誤信息。看起來像一個緊密的循環。當然,我沒有弄清楚爲什麼? 你會如此善良,並再次指向正確的方向。 請記住,我一直在做C#約6個月和TPL一個星期,否則我不會再問你。但有了這樣的經驗... 再次感謝你!
Brians代碼:
var task1 = new Task(
(obj) =>
爲什麼obj
需要?
private void Button1_Click(object sender, RoutedEventArgs e)
{
的TaskScheduler uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(); BlockingCollection blockingCollection = new BlockingCollection(); CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
Task task1 = Task.Factory.StartNew(
() =>
{
for (int i = 0; i < 10 ; i++)
{
token.ThrowIfCancellationRequested();
string code = i++.ToString() + "\t" + AsyncHttpReq.get_source_WebRequest(uriDE);
blockingCollection.Add(code);
}
}, token, TaskCreationOptions.None, TaskScheduler.Default);
task1.ContinueWith(
(antecedents) =>
{
if (token.IsCancellationRequested)
{
TxtBlock2.Text = "Task cancel detected";
}
else
{
TxtBlock2.Text = "Signalling production end";
}
blockingCollection.CompleteAdding();
}, uiTaskScheduler);
Task task2 = Task.Factory.StartNew(
() =>
{
while (!blockingCollection.IsCompleted)
{
string dlcode;
if (blockingCollection.TryTake(out dlcode))
{
TxtBlock3.Text = dlcode;
}
}
}, token, TaskCreationOptions.None, uiTaskScheduler);
}
你能粘貼完整的堆棧跟蹤嗎?另外,最初是從UI線程調用的方法是否啓動? –
是的,實際上它們是從ui線程開始的。 這一切都在以下事件宣稱: 私人無效的button1_Click(對象發件人,RoutedEventArgs E) {} 我粘貼上述堆棧。 – user774326
對不起,你能粘貼完整的異常細節(即exception.ToString())嗎?這應該絕對有效。調用調度程序[開始]調用不是必需的。此外,如果工作取消,則會出現一個錯誤,您將在非UI計劃任務(task1)中設置TextBlock2.Text。 –