.순:는 방법을 배경을 실 신호 main 스레드는 데이터가 사용할 수 있습니까?

StackOverflow https://stackoverflow.com/questions/122882

문제

는 무엇입 적절한 기술을 갖 ThreadA 신호 ThreadB 의 일부 이벤트지 않고, ThreadB 앉아서 차단된 이벤트를 기다리고 있을까?

나는 백그라운드 스레드가 채우는 것입니다 공 목록<T>.나는 방법을 찾기 위해 노력하고 비동기적으로 신호하는"주"는 스레드가 사용할 수 있는 데이터를 집어 들었다.


i 을 설정하는 것으로 간주는 이벤트 EventWaitHandle 개체 수는 없지만 내 main 스레드에 앉아있는 이벤트입니다.WaitOne().


내가 간주되는 대리인을 콜백하지만, a)내가 원하지 않는 주요 작업을 수행하는 스레드에서 대리인:스레드를 얻을 필요가 다시 작업을 더 추가하면 저는 그것을 원하지 않기를 기다리고 있는 대리자가 실행 b)위임해야에 배열된 주요 실은,그러나 나를 실행하지 않 UI,내가 통제 할 수 없습니다.대리자를 호출합니다.


내가 간주되는 대리인 콜백을 시작 단순히 제 간격이 시스템입니다.Windows.Forms.타이머(레스 타이머 동기화된).이 방법은 실만 붙어 있으로 통화

Timer.Enabled = true;

하지만 그는 것 같습니다.

옛날에 나체가 만든 숨겨진 창고 스레드에 메시지를 게시하는 숨겨진 윈도우'HWND.내가 생성을 고려 숨겨진 제어지만,나를 수집할 수 없습니다.에 대한 호출을 통제 손잡이가 없는 만들어집니다.Plus,i have no UI:내 개체 수에서 만들어졌는 웹 서버,서비스,또는 콘솔,나는 원하지 않는다고 있는 그래픽 제어 나타나-나고 싶은 컴파일에 의존성 시스템입니다.Windows.Forms.


i 을 갖는 것으로 간주 내체 노출 ISynchronizeInvoke 인터페이스,하지만 그런 다음 필요가 구현할 수 있습니다.Invoke(),그리고 내 문제입니다.


는 무엇입 적절한 기술을 실 신호 실 B 의 일부 이벤트지 않고,스레드 B 앉아서 차단된 이벤트를 기다리고 있을까?

도움이 되었습니까?

해결책

다음은 System.componentModel.backgroundworker 클래스의 코드 샘플입니다.

    private static BackgroundWorker worker = new BackgroundWorker();
    static void Main(string[] args)
    {
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.WorkerReportsProgress = true;

        Console.WriteLine("Starting application.");
        worker.RunWorkerAsync();

        Console.ReadKey();
    }

    static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        Console.WriteLine("Progress.");
    }

    static void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        Console.WriteLine("Starting doing some work now.");

        for (int i = 0; i < 5; i++)
        {
            Thread.Sleep(1000);
            worker.ReportProgress(i);
        }
    }

    static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("Done now.");
    }

다른 팁

나는 결합하는 몇 가지 응답이 여기 있다.

는 이상적인 상황을 사용하 thread-safe 플래그 등 AutoResetEvent.지 무제한으로 차단할 때는 전화 WaitOne(), 사실,그것은 하중 초과할 수 있는 지정한다.이 과부하환 false 는 경우 이 플래그 설정하지 않은 간격 동안.

A Queue 은 더 이상적인 구조에 대한 생산자/소비자의 관계,하지만 당신은 그것을 흉내낼 수 있는 경우에 당신의 요구 사항은 당신이 사용하도록 강요하는 List.주요 차이점은 당신이해야 할 것을 보장하는 소비자 잠금 컬렉션에 대한 액세스 동안 추출하는 아이템가장 안전한 것은 아마 사용 CopyTo 방법을 모두 복사하는 요소를 배열한 다음,잠금을 해제하십시오.물론,도록 귀하의 프로듀서 시도하지 않습 업데이트 List 잠금이 설정되어 있는 동안 개최됩니다.

여기에 간단한 C#콘솔 응용 프로그램을 보여 주는 방법이 될 수 있을 구현했습니다.을 재생하는 경우와 주변 간격으로 타이밍을 일으킬 수 있는 다양한 일이 일어날;이는 특정 구성하려고 노력했는 생산자가 생성하는 여러 항목을하기 전에 소비자는 검사에 대한 항목입니다.

using System;
using System.Collections.Generic;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        private static object LockObject = new Object();

        private static AutoResetEvent _flag;
        private static Queue<int> _list;

        static void Main(string[] args)
        {
            _list = new Queue<int>();
            _flag = new AutoResetEvent(false);

            ThreadPool.QueueUserWorkItem(ProducerThread);

            int itemCount = 0;

            while (itemCount < 10)
            {
                if (_flag.WaitOne(0))
                {
                    // there was an item
                    lock (LockObject)
                    {
                        Console.WriteLine("Items in queue:");
                        while (_list.Count > 0)
                        {
                            Console.WriteLine("Found item {0}.", _list.Dequeue());
                            itemCount++;
                        }
                    }
                }
                else
                {
                    Console.WriteLine("No items in queue.");
                    Thread.Sleep(125);
                }
            }
        }

        private static void ProducerThread(object state)
        {
            Random rng = new Random();

            Thread.Sleep(250);

            for (int i = 0; i < 10; i++)
            {
                lock (LockObject)
                {
                    _list.Enqueue(rng.Next(0, 100));
                    _flag.Set();
                    Thread.Sleep(rng.Next(0, 250));
                }
            }
        }
    }
}

지 않은 경우 차단하려는 생산자 모두에서,그것은 조금 더 까다 롭습니다.이 경우에는 것이 좋을 만드는 생산자는 자신의 클래스 모두 개인적이고 공공 버퍼 및 공개 AutoResetEvent.생산자는 기본적으로 저장소 항목에서 버퍼를 하려고 하면 다음에 기록하는 공공 버퍼입니다.소비자가 공공 버퍼,그것은 다시 플래그에서 프로듀서 객체입니다.하기 전에 프로듀서로 이동하려고 항목에서 버퍼를 대중 버퍼,이 검사 이 플래그과 복사본만 항목을 때 소비자에 작동하지 않습니다.

배경 작업자를 사용하여 두 번째 스레드를 시작하고 진행중인 이벤트를 사용하여 다른 스레드에 데이터가 준비되었음을 알립니다. 다른 이벤트도 제공됩니다. 이 MSDN 기사는 당신을 시작해야합니다.

정확히 무엇을하고 싶은지에 따라이 작업을 수행하는 방법에는 여러 가지가 있습니다. ㅏ 생산자/소비자 대기열 아마 당신이 원하는 것일 것입니다. 스레드에 대한 심도있는 자세한 내용은 다음의 장을 참조하십시오. 스레딩 훌륭한 책에서 (온라인 가능) 간단히 말해서 C# 3.0.

Autoresetevent (또는 ManualResetevent)를 사용할 수 있습니다. autoresetevent.waitone (0, false)을 사용하는 경우 차단되지 않습니다. 예를 들어:

AutoResetEvent ev = new AutoResetEvent(false);
...
if(ev.WaitOne(0, false)) {
  // event happened
}
else {
 // do other stuff
}

이 경우 BackgroundWorker 클래스는 답변입니다. 비동기 적으로 메시지를 보낼 수있는 유일한 스레딩 구조입니다. 그것은 배경 worker 객체를 만들었습니다. 내부적 BackgroundWorker 사용 AsyncOperation 전화로 클래스 asyncOperation.Post() 방법.

this.asyncOperation = AsyncOperationManager.CreateOperation(null);
this.asyncOperation.Post(delegateMethod, arg);

.NET 프레임 워크의 다른 클래스도 비동기 작용을 사용합니다.

  • 배경 노동자
  • SoundPlayer.loadAsync ()
  • smtpclient.sendasync ()
  • ping.sendasync ()
  • WebClient.DownloadDataAsync ()
  • WebClient.DownloadFile ()
  • WebClient.DownloadFileAsync ()
  • 웹 클라이언트 ...
  • Pictubbox.loadasync ()

"기본"스레드가 Windows Message Pump (GUI) 스레드 인 경우 양식을 사용하여 폴링 할 수 있습니다. Timer- 작업자 스레드에서 데이터를 얼마나 빨리 '통지'해야하는지에 따라 타이머 간격을 조정하십시오. .

공유에 대한 액세스를 동기화해야합니다 List<> 당신이 사용할 경우 foreach, 피하기 위해 CollectionModified 예외.

실시간 거래 응용 프로그램에서 모든 시장 데이터 중심 GUI 업데이트 에이 기술을 사용하며 매우 잘 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top