[EDIT] umformuliert und Simplified ganzen Beitrag [/ EDIT]Wie ein Synchronisationskontext für die zweite Form erhalten gezeigt
In diesem blog, die folgenden (ich es ein wenig vereinfacht) gegeben ist als ein Beispiel eines SynchronizationContext Ziel der Verwendung eine Aufgabe auf dem UI-Thread ausgeführt wird:
Task.Factory.StartNew(() =>"Hello World").ContinueWith(
task => textBox1.Text = task.Result,
TaskScheduler.FromCurrentSynchronizationContext());
ich diese Ergebnisse in einem neuen Projekt wiederholen, die Benutzeroberfläche sicher zu aktualisieren, aber aus irgendeinem Grunde in meinem aktuellen Projekt (auch wenn es war funktioniert) Ich kann nicht. Ich bekomme den Standard "Du darfst nicht die UI von der falschen Thread-Ausnahme aktualisieren".
Mein Code (in MainForm_Load (...)) ist wie diese, die w/a textBox1 hinzugefügt, um die Haupt-Form in einem frischen Projekt arbeitet, funktionieren aber nicht in meinem aktuellen Projekt:
var one = Task.Factory.StartNew(
() => "Hello, my name is Inigo Montoya");
var two = one.ContinueWith(
task => textBox1.Text = one.Result,
TaskScheduler.FromCurrentSynchronizationContext());
Jeder hat irgendwelche Gedanken darüber, was Gong sein könnte.
[EDIT]
ich den Fehler zurückverfolgt haben zurück in die Instanziierung eines Objekts, das ein Formular verwendet die Benutzer-Anmeldeinformationen aufzufordern. Der Fehler tritt nur auf, wenn das Formular angezeigt wurde. (Wenn ich einen fest codierten Wert zurückgebe, bevor die Show
dieses Formulars passiert, funktioniert die ganze Sache gut).
Neue Frage: Wie bekomme ich den SynchronizationContext für das Formular, das ich konstruiere, wenn sein eigener Konstruktor ein anderes Formular anzeigt, bevor es angezeigt wurde? Hier ist, wie können Sie reproduzieren, was passiert:
1) Erstellen Sie zwei Formulare: Form1 mit einem TextBox
und Form2 mit einem Button
2) Erstellen Sie eine Klasse OwnedBy1Uses2
Form1
:
public partial class Form1 : Form
{
OwnedBy1Uses2 member;
public Form1()
{
InitializeComponent();
member = new OwnedBy1Uses2();
}
private void Form1_Load(object sender, EventArgs e)
{
var ui = TaskScheduler.FromCurrentSynchronizationContext();
Task<string> getData = Task.Factory.StartNew(
() => "My name is Inigo Montoya...");
Task displayData = getData.ContinueWith(
t => textBox1.Text = t.Result, ui);
}
}
:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
DialogResult = System.Windows.Forms.DialogResult.Cancel;
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult = System.Windows.Forms.DialogResult.OK;
Hide();
}
}
OwnedBy1Uses2
:
class OwnedBy1Uses2
{
int x;
public OwnedBy1Uses2()
{
using (Form2 form = new Form2())
{
if (form.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
x = 1;
}
else
{
x = 2;
}
}
}
}
Ich dachte, der ganze Sinn einer Aufgabe war es asynch und per Definition, die in einem anderen Thread sein sollte. Sie können auf ein Steuerelement aus einem anderen Thread nicht zugreifen, wie Sie wissen. –
Weitere Details: Ich lade Objekte aus einer Datenbank Asynch (sehr langwieriger Prozess). Wenn das erledigt ist, habe ich "displayItems" als einen sehr schnell laufenden Prozess definiert, der die Benutzeroberfläche aktualisiert. Der * andere * Punkt einer Task ist das Timing/Ordering von asynchronen Prozessen/Threads. Dies ist die Aufgabe von displayItems: "Wenn previousTask fertig ist, zeigen Sie die geladenen Elemente an" – Crisfole
Wenn Sie den System.Threading.Task-Namespace verwenden, verwendet Ihre Aufgabe einen CLR-Thread-Pool-Thread. Dies ist also nicht mehr Ihr UInthread . Überprüfen Sie diese: http://www.eggheadcafe.com/tutorials/aspnet/21013a52-fe11-4af8-bf8b-50cfd1a51577/task-parallelism-in-c-4.aspx –