Pregunta

[EDIT] reformulado y toda simplificado poste [/ EDIT]

En este el blog , la siguiente (I simplifica un poco) se da como un ejemplo del uso de un objeto SynchronizationContext para ejecutar una tarea en el subproceso de interfaz de usuario:

Task.Factory.StartNew(() =>"Hello World").ContinueWith(
            task => textBox1.Text = task.Result,
            TaskScheduler.FromCurrentSynchronizationContext());

Me puede repetir estos resultados en un nuevo proyecto, la actualización de la interfaz de usuario de forma segura, pero por alguna razón en mi proyecto actual (aunque es estado de trabajo) no puedo. Me da la norma "Usted no tiene permiso para actualizar la interfaz de usuario del hilo equivocado" excepción.

Mi código (en MainForm_Load (...)) es así, que trabaja en un nuevo proyecto w / a textBox1 añadida a la forma principal, pero no funciona en mi proyecto actual:

var one = Task.Factory.StartNew(
        () => "Hello, my name is Inigo Montoya");
var two = one.ContinueWith(
        task => textBox1.Text = one.Result,
        TaskScheduler.FromCurrentSynchronizationContext());

Alguien tiene alguna idea de lo que podría ser el gong.

[EDIT]

he rastreado la parte posterior de error a la ejecución de un objeto que utiliza un formulario para solicitar al usuario información de acceso. El error sólo ocurre cuando la forma se ha demostrado. (Si vuelvo un valor codificado antes de que Show del Formulario pasa toda la cosa funciona bien).

Nueva pregunta: ¿Cómo puedo obtener el SynchronizationContext de la forma que estoy construyendo, si sus propias pantallas constructor otra forma antes de que se ha demostrado? He aquí cómo usted puede reproducir lo que está sucediendo:

1) Crear dos formas: Form1 con un TextBox, y Form2 con un Button

2) Crear un OwnedBy1Uses2 clase

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;
            }
        }
    }
}
¿Fue útil?

Solución

Sólo estar en el hilo principal no es suficiente. Es necesario tener un SynchronizationContext.Current válida (establecer un punto de interrupción en la línea FromCurrentSynchronizationContext y examinar el valor de SynchronizationContext.Current; si se trata de null, entonces mal de algo).

La solución más limpia es para ejecutar el código de tarea, incluyendo FromCurrentSynchronizationContext desde dentro del bucle de mensajes de interfaz de usuario -., Es decir, de algo así como Form.Load para Windows Forms o WPF para Window.Loaded

Editar

Se produjo un error en Windows Forms, donde ponerla En Form.Load no fue suficiente, ya sea - que en realidad tenía que forzar la creación de mango Win32 leyendo la propiedad Handle. Yo tenía la impresión de que este error se había fijado, pero podría estar equivocado.

Editar 2 (copiado de comentario):

Sospecho que su problema es que usted está llamando fuera de ShowDialog Application.Run. ShowDialog es un bucle de mensajes anidados, pero en este caso no hay ningún bucle de mensajes de los padres. Si se establece una vigilancia sobre SynchronizationContext.Current y el paso a través de la ShowDialog, verá que se trata de un WindowsFormsSynchronizationContext antes de que se muestre el diálogo, pero cambia a un SynchronizationContext no WinForms después de que el diálogo se muestra. Mover la creación miembro (incluyendo el ShowDialog) de las correcciones de eventos Load el problema.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top