C # - отправить ссылку на интерфейс пользователя Task.Factory.StartNew () ;? - PullRequest
1 голос
/ 05 декабря 2010

Как бы вы отправили / передали ссылки на экземпляры для новой задачи?

Допустим, у меня есть это:

    public BlockingCollection<string> blockingCollection = new BlockingCollection<string>();
    textBox_txt.Text = "Result: ";
    public Task t = Task.Factory.StartNew(() =>
    {
        foreach (string value in *???1*.blockingCollection.GetConsumingEnumerable())
        {
            *???1*.blockingCollection.Take() 
            [...bla...]
            *???2*.Invoke(new updateTextBox_txtCallback(*???2*.updatetextBox_txt)
                          , new object[] { "THE RESULT!\r\n" });
        }                
    });

Я предполагаю, что где-то здесь StartNew(() =>Я должен передать ссылки на blockingContent и textBox.Я посмотрел вокруг, но не смог понять синтаксис.(это довольно волосато)

Помогите, пожалуйста.

[Edit] Итак, если я вызываю статический объект с помощью Task, он, очевидно, работает;но мне нужна задача для работы с экземплярами;а именно blockingCollection и updateTextBox_txtCallback Invoke.

Ответы [ 2 ]

1 голос
/ 05 декабря 2010

Я воспроизвел вашу проблему, с обходным путем ниже.Проблема в том, что вы используете Task в качестве поля в вашем классе, чтобы он мог ссылаться только на статические члены, поскольку экземпляр не был создан до запуска конструктора (инициализаторы поля вызываются до инициализации класса).Из спецификации C # (10.5.5.2):

Инициализатор переменной для поля экземпляра не может ссылаться на создаваемый экземпляр.Таким образом, это ошибка времени компиляции, чтобы ссылаться на это в инициализаторе переменной, так как это ошибка времени компиляции для инициализатора переменной, чтобы ссылаться на любой элемент экземпляра через простое имя.В примере класс A {int x = 1;int y = x + 1;// Ошибка, ссылка на член экземпляра этого} инициализатор переменной для y приводит к ошибке во время компиляции, поскольку она ссылается на член создаваемого экземпляра.

В основном у вас есть две опции:

  1. Инициализируйте переменную Task в конструкторе
  2. Используйте метод для извлечения

Пример:

public class Foo
{
    public string myProperty = "foobar";
    public Task t;

    public Foo()
    {
        t = Task.Factory.StartNew(() =>
        {
            myProperty = "test";

        });
    }

    //THIS won't compile
    //public Task t = Task.Factory.StartNew(() =>
    //{
    //    myProperty = "test";

    //});

    public Task GetTask()
    {
        Task t = Task.Factory.StartNew(() =>
        {
            myProperty = "test";

        });
        return t;
    }
}
1 голос
/ 05 декабря 2010

Вам не нужно передавать ссылку, потому что C # поддерживает замыкания .Простое использование переменной, содержащей эту ссылку внутри вашего блока StartNew, заставит компилятор сгенерировать код, упаковывающий вашу ссылку в объект состояния, который передается анонимному методу:

textBox_txt.Text = "Result: ";
public Task t = Task.Factory.StartNew(() =>
{
    // use textBox_txt in this block - the compiler
    // will handle the passing of actual reference to the
    // anonymous method for you                
});

Я настоятельно рекомендую Красота замыканий для получения дополнительной информации об этой функции.

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

...