views:

75

answers:

1

I have a WPF form with ListView (resultsList) and I have a static method Fetcher, which returns results of the search for some information over the webpage with pagination (all pages at once, or one return for each page). It is done using WebClient so fetching 40 sites takes about 2 minutes. I don't want to appear the results immediately after the search is done, but I want them to apear on the resultList as they are collected - so by parts, so the user can stop the search if something useful is found. It's like the search in the Windows - results apear continuously as something is found, not all at once.

I think it's quite common problem in multithreading apps, wich I can't overcome.

+2  A: 

You need a Backgroundworker. Below, LoadChunk procedure is called on the parallel thread, but ChunkLoaded is called on the main thread, so you accumulate results in a temp list in the LoadChunk but then when you call ReportProgress on the worker, you can fill the main UI-bound collection from the temp list.

    public void LoadDataAsync()
    {
        ...
        BackgroundWorker bw = new BackgroundWorker();
        bw.WorkerReportsProgress = true;
        bw.DoWork += LoadChunk;
        bw.ProgressChanged += new ProgressChangedEventHandler(ChunkLoaded);
        bw.RunWorkerAsync();
    }

    void ChunkLoaded(object sender, ProgressChangedEventArgs e)
    {
       PopulateDataToUI();
    }

    private void LoadChunk(object sender, DoWorkEventArgs e)
    {
        int chunkNum = 0;
        BackgroundWorker bw = (BackgroundWorker)sender;
        bw.ReportProgress(chunkNum++);
        while (true)
        {
           ...   
           bw.ReportProgress(chunkNum++);
           if (done) then break;
        }
    }

EDIT: I don't lock anything - LoadChunk reads into a private collection and ChunkLoaded transfers from private collection into an observable collection. While only one BackgroundWorker works with this private collection, no conflict can occur.

Sergey Aldoukhov
Thanks! Work like a charm for me. It's important to add, that you have to somehow pass a chunk to ChunkLoaded. It's not possible to be done with bw.ReportProgress(chunkNum++, chunk); so with the userState because it's some kind of bug in .NET and userState in ChunkLoaded is always null. So probably you have to create temporary list in main thread, lock it in LoadChunk, fill, unlock and then use it in ChunkLoaded. Or you have better idea?
Łukasz Sowa