извикване по време на фонов работник

Трябва да извикам това: string input_ip_r = listView1.Items[lc].SubItems[1].Text; затова използвах

if (InvokeRequired)
{
    this.Invoke(new MethodInvoker(function));
    return;
}

Това проработи, но сега го поставих в BackgroundWorker и използвам това

if (InvokeRequired)
{
    this.Invoke(new MethodInvoker(bw.RunWorkerAsync));
    return;
}

дава грешка, че можете да стартирате BackgroundWorker само един по един.

И така, как да извикам, докато съм в Backgroundworker?


person Dasher Labs    schedule 19.12.2012    source източник
comment
Добре, объркан съм. a) защо да поставите кода за достъп до потребителския интерфейс във фонов работник? b) опитвате ли се да стартирате bw.RunWorkerAsync от bw.DoWork?   -  person Mike Park    schedule 20.12.2012
comment
Какво имаш предвид? Предполага се, че първият код се изпълнява от фоновата нишка (извиквайки UI нишката). Вторият код изглежда сякаш се опитва да извика фоновата нишка.   -  person Mario S    schedule 20.12.2012
comment
Низът трябва да бъде извикан и не мога да разбера как да направя това по време на фоновия работник, новият MethodInvoker се опитва да го изпълни втори път   -  person Dasher Labs    schedule 20.12.2012


Отговори (2)


Не съм съвсем сигурен как искате да използвате стойностите, но само за да ви дам пример, можете лесно да направите това в нишката BackgroundWorker:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    string input_ip_r = "";
    this.Invoke(new Action(() => 
    {
        // Don't know what "lc" is (a loop variable?)
        input_ip_r = listView1.Items[lc].SubItems[1].Text;
    }));
}

Вижте този отговор за други начини да направите същото (това е за >= .Net 3.5)

person Mario S    schedule 19.12.2012
comment
Радвам се, че работи за вас =) Не забравяйте обаче, че това е само един от начините, по които можете да го използвате. Отговорът на @Servy има точки, които също трябва да бъдат взети предвид. - person Mario S; 20.12.2012

1) Не поставяйте RunWorkerAsync като метод за извикване. Всъщност не изпълнява метода, който мислите. Това, което наистина трябва да поставите там, е нещо подобно:

this.Invoke(new MethodInvoker(MethodToUpdateUI));

MethodToUpdateUI трябва да бъде някакъв нов метод, който създавате, който конкретно прави всички актуализации на потребителския интерфейс, които трябва да бъдат направени в този контекст.

2) Няма нужда от InvokeRequired. Вие сте във фонова тема. Винаги ще се изисква извикване.

Честно казано, цялата схема на if(invoke required) call myself else do stuff е странна конструкция, която не харесвам. InvokeRequired трябва да се използва доста рядко. Почти винаги трябва да знаете дали сте в нишката на потребителския интерфейс или фоновата нишка, ако не го направите, има вероятност нещо да не е наред (или винаги сте в едната или другата и просто не знаете коя, или не трябва да бъде недетерминистично). Обикновено това означава да имате методи, които трябва да се изпълняват в нишката на потребителския интерфейс. Ако вече сте в нишката на потребителския интерфейс, вие просто ги извиквате, ако сте във фонова нишка и знаете това, тогава първо извиквате Invoke.

Освен това Invoke работи добре, дори ако го извикате, когато вече сте в нишката на потребителския интерфейс, така че наистина няма значителни отрицателни последици от просто извикване на Invoke, независимо дали сте във фонова нишка или вече сте в потребителския интерфейс резба.

3) Обикновено е най-добре да отделите кода за решаване на бизнес проблеми от UI кода. Миризмата на код трябва да се извиква от манипулатора на DoWork. Ако това е точно към края, вероятно трябва да добавите манипулатор на събития към RunWorkerCompleted. Ако извиквате това периодично, за да актуализирате потребителския интерфейс с напредъка на работника, трябва да използвате ReportProgress и да обработвате събитието ProgressReported. За да получите информация от потребителския интерфейс за използване в дълго изпълнявана задача, трябва да получите достъп до нея, преди да стартирате фоновата задача. За изключителни случаи, които не са нито един от тези, може да е подходящо да използвате Invoke, но останалите случаи трябва да са редки.

person Servy    schedule 19.12.2012
comment
Трябва да задам тази стойност listView1.Items[lc].SubItems[1].Text във фоновия работник без извиквания на кръстосани нишки - person Dasher Labs; 20.12.2012
comment
@user1335937 Добре. Това е, което моят отговор ви помага да се справите. - person Servy; 20.12.2012
comment
Аз съм съвсем нов в c#, ​​така че имам цикъл за получаване на всеки елемент от списъка от подточка 2 и как да го вкарам във фоновия работник, за да го използвам? - person Dasher Labs; 20.12.2012
comment
@user1335937 Извадете всички елементи от списъка и ги поставете в структура от данни, като List или масив. След това го запазете като частно поле за екземпляр и го използвайте във фоновия работник. По този начин на първо място нямате достъп до потребителския интерфейс от фоновия работник. - person Servy; 20.12.2012