[編集]投稿全体を言い換えて簡略化[/編集]
このブログでは、SynchronizationContext オブジェクトを使用して UI スレッドで Task を実行する例として、次の (少し簡略化しました) を示します。
Task.Factory.StartNew(() =>"Hello World").ContinueWith(
task => textBox1.Text = task.Result,
TaskScheduler.FromCurrentSynchronizationContext());
新しいプロジェクトでこれらの結果を繰り返し、UI を安全に更新することはできますが、現在のプロジェクトでは何らかの理由で (それが機能していたとしても) できません。標準の「間違ったスレッドから UI を更新することはできません」という例外が発生します。
私のコード(MainForm_Load(...)内)は次のようなもので、メインフォームにtextBox1が追加された新しいプロジェクトで機能しますが、現在のプロジェクトでは機能しません:
var one = Task.Factory.StartNew(
() => "Hello, my name is Inigo Montoya");
var two = one.ContinueWith(
task => textBox1.Text = one.Result,
TaskScheduler.FromCurrentSynchronizationContext());
誰でも何が起こっているのかについて考えを持っています。
[編集]
フォームを使用してユーザーにログイン情報を求めるオブジェクトのインスタンス化にまでさかのぼってエラーをたどりました。エラーは、フォームが表示されている場合にのみ発生します。(そのフォームが発生する前にハードコードされた値を返すとShow
、すべてが正常に機能します)。
新しい質問: 独自のコンストラクターが表示される前に別のフォームを表示する場合、作成中のフォームの SynchronizationContext を取得するにはどうすればよいですか? 何が起こっているかを再現する方法は次のとおりです。
1) 2 つのフォームを作成しTextBox
ます。Button
2) クラスを作成する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);
}
}
Form2
:
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;
}
}
}
}