Управление безопасностью потоков - Crashing VS 2008 - PullRequest
0 голосов
/ 09 июля 2009

Я работаю над созданием потокаобезопасного элемента управления для моего приложения Windows Forms.

Я понимаю, что могу установить текст в безопасном потоке управления, используя следующий код:

private delegate void SetTextD(Control control, string value);

private static void SetText(Control control, string value)
{
    if(control.InvokeRequired)
    {
        control.Invoke(new SetTextD(SetText), new object[] {control, value});
    }
    else
    {
        control.Text = value;
    }
}

Тогда в моем коде формы я могу позвонить:

SetText(lblStatus, "Updating...");

Моя цель - создать пользовательский элемент управления, который наследует Label. Затем внутри этого класса в свойстве Text я могу просто вызвать:

lblStatus.Text = "Обновление ..."

Тогда он автоматически сделает правильный потокобезопасный код.

Вот код, который я имею в своем классе:

public class ThreadSafeLabel : Label 
{
    private delegate string GetTextD();
    private delegate void SetTextD(string value);

    private string GetText()
    {
        if (InvokeRequired)
        {
            return (string)Invoke(new GetTextD(GetText));
        }
        return Text;
    }

    private void SetText(string value)
    {
        if(InvokeRequired)
        {
            Invoke(new SetTextD(SetText), new object[] {value});
        }
        else
        {
            Text = value;
        }
    }

    public override string Text
    {
        get
        {
            return GetText();
        }
        set
        {
            SetText(value);
        }
    }
}

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

Есть мысли о том, что я могу делать неправильно или чего мне не хватает?

Если что-то не понятно, спросите.

Спасибо!

Ответы [ 2 ]

2 голосов
/ 09 июля 2009

Попробуйте

return base.Text;

или вы попадете в бесконечный цикл (когда вы добавляете метку в форму, запрашивается свойство Text - и бесконечный цикл приводит к сбою VS). То же самое для вашего сеттера.

1 голос
/ 09 июля 2009

Из-за анонимных методов в C # 3.0 вам не нужны отдельные методы set и get. Самый простой способ сделать то, что вы ищете, выглядит так:

public class ThreadSafeLabel : Label {
    public override string Text {
        get {
            return InvokeRequired ? Invoke(new Func<string>(() => base.Text)) : base.Text;
        }
        set { 
            if (InvokeRequired)
                BeginInvoke(new Action(() => base.Text = value));
            else
                base.Text = value;
        }
}

Обратите внимание, что я использую BeginInvoke, так что вызывающий поток не будет ждать завершения вызова; Вы можете изменить его на Invoke.

EDIT

Проблема с вашим кодом состоит в том, что ваши методы set и get снова вызывают ваше переопределенное свойство Text, создавая цикл infinte, который приводит к переполнению стека (исключение, а не веб-сайт). Вам нужно написать base.Text для вызова реализации базового класса свойства Text.

...