0 / 0 / 0
Регистрация: 25.12.2011
Сообщений: 6
1

Как передать параметры в BackgroundWorker

10.01.2012, 21:25. Показов 15442. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте. В общем надо чтобы при нажатии на кнопку выполнялась операция, но т.к. она длительная, то окно виснет до тех пор пока операция не закончится. Мне нужно наоборот, чтобы вовремя этой операции производилось логирование и отображался прогресбар(всмысле показывал сколько проделано), ну и конечно, чтобы пользователь мог параллельно с выполнением этой операцией пользоваться программой. Нашел отличный выход с ситуации backgroundWorker, но как всегда, есть "но" - мне нужно внести в backgroundWorker несколько параметров с основного потока, нашел вот такой код:

C#
1
2
3
4
5
6
7
8
9
10
11
12
struct BackgroundWorkParams
        {
            public string param1 = pausa.SelectionBoxItem.ToString();
            public string param2 = countadd.Text;
            //ну и еще несколько
        }
 
private void BackgroundWorker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            BackgroundWorkParams param = (BackgroundWorkParams)e.Argument;
            ....
Но тут ошибки:
"в структуре не могут содержаться инициализаторы полей экземпляров" и
"для нестатического поля, метода или свойства требуется ссылка на объект"

Как правильно передать параметры? Или может есть какой-нибудь другой способ для моей задачи?

Заранее спасибо!
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.01.2012, 21:25
Ответы с готовыми решениями:

Как передать параметры в backgroundWorker
Подскажите пожалуйста решение проблемы. Есть функция public Start(int i); Сейчас она выполняется...

Как передать по ссылке параметр в BackgroundWorker
Есть собственный компонент (выполняет запрос к таблице БД), который инициализируется следующим...

Как передать параметры функции?
Как правильно прописать, чтобы передались параметры функции? Option Compare Database Option...

Как передать параметры в WORD?
Помогите пожалуйста. Есть шаблон для WORD'а он содержит модуль DrawPicture, а он в свою очередь...

20
352 / 331 / 49
Регистрация: 12.12.2011
Сообщений: 563
10.01.2012, 21:50 2
C#
1
2
3
4
5
6
7
8
9
10
private void SetTextSafe(string text) {
            if (InvokeRequired)
                this.BeginInvoke(new Action<string>((s) => {
                    SetText(s);
                }), text);
            else SetText(text);
        }
private void SetText(string text) {
            this.Text = text; //Заголовок формы = текст
        }
Как то так.

вызывать естественно
C#
1
SetTextSafe("ТУТ ТЕКСТА НЕТ");
Добавлено через 14 минут
Или вот так:
C#
1
2
3
4
5
void SetTextSafe(string text)
{
    if (textBox1.InvokeRequired) textBox1.Invoke(new Action<string>((s) => textBox1.Text = s), newText);
    else textBox1.Text = text;
}
, а вообще лучше почитайте Ответы на 7 самых частых вопроса по WinForms
1
42 / 36 / 2
Регистрация: 18.12.2011
Сообщений: 113
10.01.2012, 21:50 3
1. Если вам непонятны эти ошибки - почитайте любую литературу по азам C#.
1.1 Если вы хотите задать начальные значения для этих переменных, используйте конструктор.
2.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public int main()
{
BackgroundWorker_DoWork(this, new MYARGS("my first param", "my second param"));
}
public void BackgroundWorker_DoWork(object sender, DoWorkEventArgs args)
{
//...
}
public class MYARGS: DoWorkEventArgs
{
public string param1,param2;//....
public MYARGS(string Param1, string Param2)
{
this.param1 =Param1;
this.param2 = Param2;
}
}
1
Эксперт .NET
17203 / 12657 / 3321
Регистрация: 17.09.2011
Сообщений: 20,932
10.01.2012, 22:08 4
iTheSaboteur, какое-то странное использование DoWorkEventArgs у вас.


code2l, в качестве быстрого фикса можете заменить struct на class и ошибки не будет.
1
42 / 36 / 2
Регистрация: 18.12.2011
Сообщений: 113
10.01.2012, 23:18 5
kolorotur, а что именно странно?)
code2l, на всякий случай - в методе BackgroundWorker_DoWork args надо будет использовать явно приводя к MYARGS
0
0 / 0 / 0
Регистрация: 25.12.2011
Сообщений: 6
11.01.2012, 01:26  [ТС] 6
Всем спасибо.
kolorotur, изменил. Ошибка:
"для нестатического поля, метода или свойства требуется ссылка на объект" все равно выбивает, когда пытаюсь передать значение textbox'a:
C#
1
2
3
4
class BackgroundWorkParams
        {
            public string Param2 = logtext.Text;
        }
iTheSaboteur, по разному пытался, что-то не хочет работать или это у меня руки кривые.
Может есть какой-то проще вариант передать значения с контролов в BackgroundWork?
И извиняюсь, забыл уточнить, работаю в WPF, а не в WinForms.

Если создам поток с помощью
C#
1
Thread worker = new Thread()
и сделаю его фоновым через
C#
1
worker.IsBackground = true;
, код в потоке будет выполнятся т.к. мне нужно?
В общем надо чтобы при нажатии на кнопку выполнялась операция, но т.к. она длительная, то окно виснет до тех пор пока операция не закончится. Мне нужно наоборот, чтобы вовремя этой операции производилось логирование и отображался прогресбар(всмысле показывал сколько проделано), ну и конечно, чтобы пользователь мог параллельно с выполнением этой операцией пользоваться программой.
0
Эксперт .NET
17203 / 12657 / 3321
Регистрация: 17.09.2011
Сообщений: 20,932
11.01.2012, 01:52 7
Цитата Сообщение от iTheSaboteur Посмотреть сообщение
а что именно странно?
Да весь код странный. Мало того, что все выполняется в основном потоке, сам BackgroundWorker не используется вообще, да еще и обработчик запускается вручную с созданием своих аргументов.
Все-таки обработчик должен запускаться в ответ на событие, а не вручную из основного метода. А аргументы воркер сам передаст.


code2l, ну вы при объявлении класса пытаетесь присвоить значения переменной, находящейся в другом классе.
Надо как-то так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct BackgroundWorkerParams
{
   public string param1;
   public string param2;
}
 
void StartWorkerHere()
{
   var params = new BackgroundWorkerParams();
   params.param1 = pausa.SelectionBoxItem.ToString();
   params.param2 = countadd.Text;
 
   backgroundWorker.RunWorkerAsync(params);
}
 
void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
   var params = (BackgroundWorkerParams)e.Argument;
}
1
42 / 36 / 2
Регистрация: 18.12.2011
Сообщений: 113
11.01.2012, 02:07 8
Вариантов столько сколько нафантазируешь)
В в твоем случае можно:
•использовать ParametrizedThreadStart (передавать массив/структуру приведененную к типу object и в методе, делегат которого ты "передал" потоку (извиняюсь за кривые формулировки), привести к структуре/массиву)
•Вызвать нужную функцию, с нужными аргументами, в потоке- new Thread(delegate(){ BGWork(param1,param2...);}
•В некоторых случаях можно просто объявить пару глобальных переменных и оперировать с ними.
•И т.д.
↓↓↓
↓↓↓
C#
1
2
3
4
5
6
7
8
9
int main()
{
int a=1,b=2,c=3;
new Thread(delegate(){work(a,b,c);}).Start();
}
void work(int a,int b,int c)
{
Console.WriteLine((a*b*c).ToString());
}
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
int main()
{
//...
Thread th = new Thread(new ParametrizedThreadStart(DoBackground));
th.Start((new object[]{"это первый аргумент", "а это второй", 14f, 10, new Action(()=>{Console.WriteLine("Hello World\r\n this Application does any nonsense");}) /*....*/ }) as object);
//...
}
void DoBackground(object _args)
{
object[] args = _args as object[];
string p1=args[0] as string, p2=args[1] as string;
float Pi=args[2] as float;
int R = args[3] as int;
Action ForExample = args[4] as Action;
//...
ForExample();
Console.Writeline(p1 + p2 + (Pi*R*R).ToString());
}
}
Также классы/структуры вместо массива
1
294 / 234 / 58
Регистрация: 03.02.2011
Сообщений: 1,979
Записей в блоге: 1
12.01.2012, 01:28 9
iTheSaboteur, а каким образом передать System.__ComObject?
т.е. есть некий аддон к приложению. В нем идет присвоение некой переменной MyVar через GetActiveObject и дальше работа с присвоенной переменной.
переменная объявлена на уровне класса но в BackgroundWorker она не оперируема, программа просто вылетает (даже с блоком try-catch никаких ошибок)
Попробовал
C#
1
new Thread(delegate(){work(MyVar);}).Start();
- тоже самое.
0
42 / 36 / 2
Регистрация: 18.12.2011
Сообщений: 113
12.01.2012, 15:11 10
skilllab а что вы именно вы делаете с этим объектом?)
Уверены-ли вы что проблема вызвана именно созданием потока?
Попробуйте включить отладчик и пошагово пройтись по инструкциям.
0
294 / 234 / 58
Регистрация: 03.02.2011
Сообщений: 1,979
Записей в блоге: 1
12.01.2012, 15:31 11
iTheSaboteur,
Цитата Сообщение от skilllab Посмотреть сообщение
даже с блоком try-catch никаких ошибок
естественно с отладчиком и шел.

Добавлено через 3 минуты
Цитата Сообщение от iTheSaboteur Посмотреть сообщение
а что вы именно вы делаете с этим объектом?)
объект дает доступ к переменным и методам класса.
Т.е.
C#
1
2
3
4
5
6
7
8
9
10
SomeObject MyNew;
try
            {
                MyNew = (SomeObject)Marshal.GetActiveObject("SomeObject.Application");
            }
            catch
            {
                MessageBox.Show("Error getting Handle");
                return;
            }
Добавлено через 3 минуты
а дальше хотел так
C#
1
2
3
4
5
6
7
...
new Thread(delegate(){work(MyVar);}).Start();
...
void work(SomeObject NewObj)
{
NewObj = MyNew;
}
Добавлено через 1 минуту
SomeObject - подключенная к проекту DLL.
0
42 / 36 / 2
Регистрация: 18.12.2011
Сообщений: 113
12.01.2012, 16:04 12
skilllab, падает в какой момент? хоть в гугле глянуть что-нибудь))
0
294 / 234 / 58
Регистрация: 03.02.2011
Сообщений: 1,979
Записей в блоге: 1
12.01.2012, 16:11 13
так, если продолжить то что выше.
пытаюсь в DoWork сделать такое:
C#
1
2
SomeObject MyNew1 = null;
Work(MyNew1);
ну и дальше извлечения всяких методов из DLL
C#
1
 .... = MyNew1.SomeConst;
и вот тут то и падает, без ошибок, но с некоторым зависанием.
вечером могу даже GIF-ку сделать, чтоб показать что происходит.
0
42 / 36 / 2
Регистрация: 18.12.2011
Сообщений: 113
12.01.2012, 16:16 14
skilllab, стесняюсь спросить, а вы MyNew1 инициализируете потом, или он так и остается пустым?
0
294 / 234 / 58
Регистрация: 03.02.2011
Сообщений: 1,979
Записей в блоге: 1
12.01.2012, 21:48 15
Так а разве Work(MyNew1) не должен вернуть мне полновесную переменную?
И вот ещё что, при передаче в DoWork этой переменной, она как бы не пустая (если навести в дебаге то появится System.__ComObject). Но если попробовать просмотреть доступные методы то будет вот такое окно

Пробовал и другие методы передачи. Переменная передается, но при попытке присвоения типа MyNew1.SomeConst - программа слетает.
То что должно быть - на 2 рисунке
Миниатюры
Как передать параметры в BackgroundWorker   Как передать параметры в BackgroundWorker  
0
42 / 36 / 2
Регистрация: 18.12.2011
Сообщений: 113
12.01.2012, 21:52 16
Залейте куда-нибудь это добро, а то у меня ощущение будто мы на разных языках говорим
0
294 / 234 / 58
Регистрация: 03.02.2011
Сообщений: 1,979
Записей в блоге: 1
12.01.2012, 21:54 17
Да я б с радостью, только вот мой аддончик требует обязательного наличия самой программы с которой работает. (Solidworks)
0
42 / 36 / 2
Регистрация: 18.12.2011
Сообщений: 113
12.01.2012, 21:57 18
skilllab, хватит класса формы и класса MyNew1.
Не понимаю что у вас творится
0
294 / 234 / 58
Регистрация: 03.02.2011
Сообщений: 1,979
Записей в блоге: 1
12.01.2012, 21:59 19
Понял, тогда сделаю "программу-пример". Для полноты картины.
0
42 / 36 / 2
Регистрация: 18.12.2011
Сообщений: 113
12.01.2012, 23:54 20
Какой еще пример?.. я говорил о паре кусков кода
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.01.2012, 23:54
Помогаю со студенческими работами здесь

Как передать параметры в функцию
Пытался разобраться как передавать параметры в функцию. Если в C всё понятно func(1,2,3) То в...

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

Классы, как передать параметры
Ребят всем привет, с++ начал изучать всего 5 дней назад так что извините если вопрос будет глупым...

Как передать параметры компилятору?
В ручном режиме это решается так: 1) Открываю командную строку Visual Studio 2017 2) Прописываю...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru