c # темы и обновление дисплея - PullRequest
1 голос
/ 19 февраля 2009

У меня есть форма Windows с этикеткой и графическим окном. Для получения изображения из веб-службы я использую ветку.

Пользователь нажимает кнопку, и сначала должна отображаться метка, а затем запускается новый поток для получения изображения. Это код:

private void menuItem1_Click(object sender, EventArgs e)

{

etiquetaCargando.Visible = true;

this.Invoke(new System.Threading.ThreadStart(RequestImage));

}

Проблема в следующем: ярлык etiquetaCargando не появляется.

Я программирую на Compact Framework.

Что это происходит?

Спасибо!

Ответы [ 4 ]

3 голосов
/ 19 февраля 2009

Вы не должны называть это:

this.Invoke(new System.Threading.ThreadStart(RequestImage));

Я предполагаю, что вы здесь находитесь в тупике, поскольку метод Invoke направит делегата в поток пользовательского интерфейса, но вы ожидаете завершения своей операции.

Чтобы заставить код выполняться в другом потоке, вы должны сделать это:

private void menuItem1_Click(object sender, EventArgs e)
{
    etiquetaCargando.Visible = true;

    Thread t = new Thread(RequestImage);

    t.Start();
}

Затем в вашем методе RequestImage вы вызываете метод Invoke, передавая делегат для выполнения в потоке пользовательского интерфейса, в данном случае передавая загруженный вами образ.

3 голосов
/ 19 февраля 2009

Вопрос неясен, но, используя Invoke, вы отказываетесь от цели размещения запроса изображения в отдельном потоке. (Вы можете заметить, что ваш интерфейс перестает отвечать на запросы при выполнении запроса)

Вместо этого лучше создать новый объект потока, запустить его, а затем использовать Invoke для установки изображения (после его получения), что-то вроде

private void menuItem1_Click(object sender, EventArgs e)
{    
    etiquetaCargando.Visible = true;
    Thread reqThread =
        new Thread(new ThreadStart(RequestImage));
    reqThread.Start();
}

private void RequestImage()
{
    /* Get the image
    ...
    */
    Invoke(SetTheImage, new object[] { theImage });
}

это предполагает, что у вас есть метод SetTheImage, который фактически выполняет работу по отображению изображения в вашей форме.

0 голосов
/ 20 февраля 2009

Как уже говорили другие, вы используете вызов назад.

Мое предложение выглядит примерно так в вашем исходном обработчике:

ThreadPool.QueueUserWorkItem(RequestImage)

, а затем используйте лямбду, чтобы выполнить Invoke из RequestImage:

RequestImage()
{
  ...
  ...

  Invoke(() => { myControl.BackgroundImage = img; myControl.Width = img; etc, etc });
}

Или что-то в этом роде.

0 голосов
/ 19 февраля 2009

Вы можете сделать следующее:

private void menuItem1_Click(object sender, EventArgs e)
{
    etiquetaCargando.Visible = true;
    Thread t = new Thread(new ThreadStart(RequestImage));

    // NOTE THIS LINE
    // Without this, if your application is closed and the thread isn't,
    // it will leave your program in memory until it does
    t.IsBackground = true;

    this.Invoke(new System.Threading.ThreadStart(RequestImage));
}

private void RequestImage() 
{
    // Do the work here
    // let's assume img is the image you've got

    // Prepare a delegate to invoke
    MethodInvoker m = (MethodInvoker)delegate() {
         myImage.Image = img;
    };

    // Invoke it on the UI thread if needed, otherwise
    // do a straight invoke
    if (this.InvokeRequired)
        this.Invoke(m);
    else 
        m.Invoke();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...