Реализация BackgroundWorker в Mono GTK# Monodevelop .NET

08:03:2013 Рі.

В заметке рассматривается реализация подобия BackgroundWorker в GTK# на Mono .NET. Подобия, поскольку такой реализации, к сожалению, в наброре стандартных элементов не существует. Поэтому я разработал подобие такого класса и использую его в программах.

В противном случае необходимо было бы выходить из ситуации, используя делегаты, использовать напрямую класс Thread или искать другие методы. Все это является достаточно ресурсоемким и не совсем универсальным. А на платформе Mono .NET, кроме того, иногда наблюдаются некорректности в работе IAsyncResult. Предлагаемый класс позволяет обойти эти некорректности и с легкостью использовать возврящаемые значения из потока в GTK#.

Реализуем абстрактный класс. К примеру, BackgroundWorker - BackgroundWorker.cs:

using System;
using Gtk;
using System.Threading;

namespace X
{
    public abstract class BackgroundWorker
    {
        protected object result;
        protectedThreadNotify completed;
        protectedThread asyncThread;

        public BackgroundWorker ()
        {
           result = null;
           completed = newThreadNotify (newReadyEvent (ready));
           asyncThread = newThread(newParameterizedThreadStart(DoWork));
        }

        protected abstract void DoWork(object param = null);

        public void RunWorkerAsync(object param = null)
        {
           asyncThread.Start(param);
        }

        protected virtual void ready(){}
    }
}

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

Внутри данного класса асинхронно вызываемая функция одна - DoWork, которая запускается с помощью функции RunWorkerAsync и не может быть запущена напрямую. В эту функцию предусмотрена возможность передачи любых параметров в виде object, который также можно упустить т.к. он является параметром по умолчанию. В любом месте реализации класса-наследника мы можем вызвать completed.WakeupMain(); , выполнив, таким образом, функцию ready в родительском потоке из которого можно безопасно отображать сообщения или изменять элементы управления вашего приложения Mono.

Нужно отметить, что ready помечен как virtual и необязателен к реализации. RunWorkerAsync будет присутствовать в каждом наследнике, а DoWork необходимо будет реализовывать самостоятельно.

Теперь перейдем к созданию и использованию наследника, использующего многопоточность в Mono .NET GTK#. Для примера реализуем простой класс, проверяющий соединение с базой данных.

private classDBChecker :BackgroundWorker
{
    protected override void DoWork(object param)
    {
        result = false;

        if(param != null)
        {
            MySqlConnection dbcon;
            dbcon = newMySqlConnection(param.ToString());
            try
            {
                dbcon.Open();
                result = true;
            }
            catch { }
        }
      completed.WakeupMain();
    }

    protected override void ready()
    {
       if(this.result == null)
          return;
       if(!(this.result is bool))
          return;
       if(bool.Parse(this.result.ToString()) == true)
           MessageBox.Show("Соединение успешно установлено");
       else
           MessageBox.Show("Параметры подключения не верны");
    }
}

В этом коде result - объект, наследуемый из родительского класса, как и вызов completed.WakeupMain() .

Остается продемонстрировать вызов из программного кода:

DBChecker checker = newDBChecker();
checker.RunWorkerAsync(_connectionString);

Как видите, пользоваться асинхронным взовом с помощью подобного класса теперь легко. Данный класс легко дорабатывается до необходимого вам функционала. Здесь показана основная логика работы асинхронного вызова в Mono с подобием BackgroundWorker Windows Forms C#.

P.S:Возможно у начинающих программистов будет проблема с реализацией данного класса - если он будет реализован внутри их основного класса, то если потребуется не простое уведомление, а обращение к элементам управления или переменным основного класса - это приведет к ошибке компиляции. Как ее решить описано тут.

 

Добавить комментарий



Обновить

« TextBox или Entry enabled = false в GTK# Mono .Net   Mono MySQL подключение в .NET »
← Раньше

Фотоальбом

fotic.jpg

Облако Тегов