Как получить доступ к методам Form.cs в другом классе при наличии многопоточности С#

Возможный дубликат:
C# Downloader: следует ли использовать Threads, BackgroundWorker или ThreadPool?
C# , как достичь чего-то в текущем потоке, созданного в другом потоке?

Итак, у меня есть следующий код

Downloader.cs

class Downloader
{  
    private WebClient wc = new WebClient();
    public void saveImages(string picUrl, string path)
    {
                this.wc.DownloadFile(picUrl, path + p);
                Form1.Instance.log = picUrl + " is downloaded to folder " + path + ".";
    }
}

Form1.cs/Форма Windows

public partial class Form1 : Form
{
    static Form1 instance;
    public static Form1 Instance { get { return instance; } }

    protected override void OnShown(EventArgs e)
    {
        base.OnShown(e);
        instance = this;
    }

    protected override void OnClosed(EventArgs e)
    {
        base.OnClosed(e);
        instance = null;
    }
    public string log
    {
        set { logbox.AppendText(value); } // Logbox is Rich Text Box
    }
    private void ThreadJob()
    {
        Downloader r = new Downloader();
        r.saveImages("http://c.org/car.jpg","c:/temp/");
    }
    private void download_Click(object sender, EventArgs e)
    {
        ThreadStart job = new ThreadStart(ThreadJob);
        Thread thread = new Thread(job);
        CheckForIllegalCrossThreadCalls = false;
        thread.Start();
    }
}

Мне нужно, чтобы Form1.Instance.log = picUrl + " is downloaded to folder " + path + "."; работало без CheckForIllegalCrossThreadCalls, установленного на false, потому что я слышал, что это плохой способ делать что-то.

PS: Часть кода отсутствует, но я думаю, что соответствующая информация есть.


person Crazywako    schedule 03.02.2013    source источник


Ответы (2)


Вместо того, чтобы saveImages быть методом void и изменять форму, saveImages должен возвращать строковое значение, которое он вычисляет, и позволять форме изменять себя:

public string saveImages(string picUrl, string path)
{
            this.wc.DownloadFile(picUrl, path + p);
            return picUrl + " is downloaded to folder " + path + ".";
}

Теперь то, что вы действительно ищете, — это способ выполнения длительной задачи в фоновом потоке и обновления пользовательского интерфейса с результатом. Класс BackgroundWorker специально разработан для этой цели, и его гораздо проще использовать в приложении winform, чем напрямую работать с потоками.

Вам просто нужно создать BackgroundWorker, установить работу, которую он должен выполнять в событии DoWork, а затем обновить пользовательский интерфейс в событии RunWorkerCompleted.

В этом случае DoWork просто нужно вызвать saveImages, а затем установить Result в возвращаемое значение, а затем завершенное событие может добавить Result в поле форматированного текста. BackgroundWorker гарантирует, что завершенное событие будет запущено потоком пользовательского интерфейса.

person Servy    schedule 03.02.2013

См. документацию по BackgroundWorker или Control.Invoke. Помните, Google — ваш друг.

person Richard Schneider    schedule 03.02.2013