백그라운드 작업자에게 인수를 보내시겠습니까?


147

백그라운드 작업자에게 int 매개 변수를 보내고 싶다고 가정 해 보겠습니다.이를 어떻게 수행 할 수 있습니까?

private void worker_DoWork(object sender, DoWorkEventArgs e) {

}

이것이 worker.RunWorkerAsync ();이라는 것을 알고 있습니다. worker_DoWork에서 int 매개 변수를 사용해야한다고 정의하는 방법을 이해하지 못합니다.

답변:


235

다음과 같이 시작하십시오.

int value = 123;
bgw1.RunWorkerAsync(argument: value);  // the int will be boxed

그리고

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{
   int value = (int) e.Argument;   // the 'argument' parameter resurfaces here

   ...

   // and to transport a result back to the main thread
   double result = 0.1 * value;
   e.Result = result;
}


// the Completed handler should follow this pattern 
// for Error and (optionally) Cancellation handling
private void worker_Completed(object sender, RunWorkerCompletedEventArgs e) 
{
  // check error, check cancel, then use result
  if (e.Error != null)
  {
     // handle the error
  }
  else if (e.Cancelled)
  {
     // handle cancellation
  }
  else
  {          
      double result = (double) e.Result;
      // use it on the UI thread
  }
  // general cleanup code, runs when there was an error or not.
}

38
두 가지 주장을 어떻게 할 수 있습니까?
sooprise

3
아니면 하나 이상의 인수로 가득 찬 객체를 보내나요?
sooprise

23
@soo : 헬퍼 클래스 또는 Tuple<A,B>(C # 4 +)를 사용하십시오 (편집 : 예, 개체를 모두 묶기 위해 개체를 사용하십시오. 예를 들어 DoWorkEventArgs self 참조).
Henk Holterman 2016 년

그러나 결과를 UI에 어떻게 알립니 까?
rayray

1
@rayray : label1.Text = e.Result.ToString();, 어디에서나 안전하다고 표시했습니다.
Henk Holterman

101

이것이 이미 답변 된 질문이지만 IMO를 훨씬 쉽게 읽을 수있는 다른 옵션을 남겨 두었습니다.

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (obj, e) => WorkerDoWork(value, text);
worker.RunWorkerAsync();

그리고 핸들러 메소드에서 :

private void WorkerDoWork(int value, string text) {
    ...
}

12
나는 IMO가 무엇을 의미하는지 몰랐다. 나는 그것이 C #이라고 생각했다. 나는 롤 ... "IMO C 번호"를 봤 여기에 도착하고 대답을 얻었다 quantnet.com/threads/cc-vba-or-java.11433
electricalbah을

3 가지 매개 변수는 어떻습니까?
YukiSakura

나는 2012 년부터 .NET과 재생되지 않습니다,하지만 난 틀리지 않는 경우에 당신은 당신이 원하는 매개 변수를 추가 할 수 ... => WorkerDoWork(a, b, c);는 메소드 서명과 일치하는만큼을... WorkerDoWork(int a, string b, string c) {...
dcarneiro

1
당신이 이것을 사용한다면 (내가 시도한 것처럼), 매번 새로운 배경 작업자를 만들어야합니다 (예를 들어). 그렇지 않으면 나처럼 문제가 발생합니다. 저의 백그라운드 작업자는 이전 실행을 계속 반복합니다. 한 번 실행하면 괜찮습니다. 마지막 실행과 현재 실행을 2 번 반복했습니다. 세 번째 실행은 마지막 두 번과 현재를 반복합니다. 등
bshea

그러나 어떻게 값이 RunWorkerAsync로 전달됩니까?
CodyBugstein

47

이와 같은 여러 인수를 전달할 수 있습니다.

List<object> arguments = new List<object>();
                    arguments.Add(argument 1);
                    arguments.Add(argument 1);
                    arguments.Add(argument n);


                    backgroundWorker2.RunWorkerAsync(arguments);

private void worker_DoWork(object sender, DoWorkEventArgs e) {

  List<object> genericlist = e.Argument as List<object>;
  extract your multiple arguments from this list and cast them and use them. 

}

@missReclusive는 "genericlist"항목을 캐스트합니다. 즉, "argument 1"이 int 유형 인 경우 int argument1 = (int) genericlist [0]
Zain Ali

1
이것은 유지 관리 측면에서 나쁜 생각입니다. 적어도 당신이하고있는 일을 알아낼 수 있기 때문에 List <object>보다 구체적인 유형을 사용해야합니다 (아래 답변의 예 참조)
Denis

아마도 Tuple일반적인 객체의 목록보다는 (또는 특수화 된 클래스)를 선호 할 것입니다
James S


6

DoWorkEventArgs.Argument 특성을 확인하십시오 .

...
backgroundWorker1.RunWorkerAsync(yourInt);
...

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    // Do not access the form's BackgroundWorker reference directly.
    // Instead, use the reference provided by the sender parameter.
    BackgroundWorker bw = sender as BackgroundWorker;

    // Extract the argument.
    int arg = (int)e.Argument;

    // Start the time-consuming operation.
    e.Result = TimeConsumingOperation(bw, arg);

    // If the operation was canceled by the user, 
    // set the DoWorkEventArgs.Cancel property to true.
    if (bw.CancellationPending)
    {
        e.Cancel = true;
    }
}

5

여러 유형의 인수를 전달하려면 먼저 Object 유형의 배열에 모두 추가하고 해당 오브젝트를 RunWorkerAsync ()에 전달하십시오. 예는 다음과 같습니다.

   some_Method(){
   List<string> excludeList = new List<string>(); // list of strings
   string newPath ="some path";  // normal string
   Object[] args = {newPath,excludeList };
            backgroundAnalyzer.RunWorkerAsync(args);
      }

이제 백그라운드 작업자의 doWork 메소드에서

backgroundAnalyzer_DoWork(object sender, DoWorkEventArgs e)
      {
        backgroundAnalyzer.ReportProgress(50);
        Object[] arg = e.Argument as Object[];
        string path= (string)arg[0];
        List<string> lst = (List<string>) arg[1];
        .......
        // do something......
        //.....
       }

2
+1 이러한 방식으로 인수를 보내면 반복을 피하기 위해 각 실행마다 새 백그라운드 작업자를 시작하지 않아도됩니다. (적어도 내 앱에서는). 이 문제와 관련된 아래 내 의견을 참조하십시오. 또한 stackoverflow.com/a/12231431/503621 & stackoverflow.com/questions/12507602/…
bshea


4

항상 객체 유형 목록이 아닌 콘크리트 유형 (복합 디자인 패턴 사용)의 복합 객체를 사용해야합니다. 각각의 대상이 무엇인지 누가 기억할까요? 나중에 코드 유지 관리에 대해 생각해보십시오. 대신 다음과 같이 시도하십시오.

Public (Class or Structure) MyPerson
                public string FirstName { get; set; }
                public string LastName { get; set; }
                public string Address { get; set; }
                public int ZipCode { get; set; }
End Class

그리고:

Dim person as new MyPerson With { .FirstName = Joe”,
                                  .LastName = "Smith”,
                                  ...
                                 }
backgroundWorker1.RunWorkerAsync(person)

그리고:

private void backgroundWorker1_DoWork (object sender, DoWorkEventArgs e)
{
        MyPerson person = e.Argument as MyPerson
        string firstname = person.FirstName;
        string lastname = person.LastName;
        int zipcode = person.ZipCode;                                 
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.