Member 12741482 Ответов: 1

Обновление progressbar + clipboard.getimage () с помощью backgroundworker - WPF C#


Привет

моя программа должна экспортировать определенные файлы Excel из папки в виде изображения (в формате SVG) в другую папку. Это можно сделать с помощью методов CopyAndSaveTo и ExportRangeAsImage, и они делают свою работу.
На главном окне у меня есть кнопка, которая выполняет эти две функции при нажатии. Я хочу, чтобы пользователь, который нажимает на эту кнопку, был проинформирован (Progressbar), как далеко продвинулся этот процесс (Copy + export).
Я попытался реализовать это с помощью BackgroundWorker, и это работает только в том случае, если я комментирую следующий код (в методе ExportRangeAsImage):

Bitmap image = new Bitmap(System.Windows.Forms.Clipboard.GetImage());
image.Save(ImagePath + Path.GetFileNameWithoutExtension(file) + ".svg");


В противном случае я получаю следующее сообщение об ошибке (
перевод с немецкого):

В Системе.Исключение NullReferenceException исключение типа "системы.Drawing.dll " произошло, но это не было обработано в пользовательском коде.

Дополнительная информация: ссылка на объект не установлена на экземпляр объекта.

Если обработчик доступен для этого исключения, программа может продолжать работать безопасно.



Вот весь код:
private void UpdateDataOfLine1(object sender, ExecutedRoutedEventArgs e)
        {
            string[] files = Directory.GetFiles(RootPath);

            BackgroundWorker worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.DoWork += worker_DoWork;
            worker.ProgressChanged += worker_ProgressChanged;
            worker.RunWorkerAsync();
        }



        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            string[] files = Directory.GetFiles(RootPath);

            for (int i = 0; i < files.Length; i++)
            {
                if (files[i].Contains("$") || files[i].Contains("~") || files[i].Contains("Thumb"))
                {
                    continue;
                }

                File.Copy(files[i], DestPath + Path.GetFileName(files[i]), true);

                string newFile = DestPath + Path.GetFileName(files[i]);

                ExPortRangeAsImage(newFile);

                (sender as BackgroundWorker).ReportProgress(i);
                Thread.Sleep(100);
            }
        }



        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Status.Value = e.ProgressPercentage;
        }


        public void ExPortRangeAsImage(string file)
        {
            var ExcelApp = new Microsoft.Office.Interop.Excel.Application();

            try
            {
                if (file.Contains("BeispielDatei"))
                {
                    Workbook wb = ExcelApp.Workbooks.Open(file);
                    Worksheet ws = (Worksheet)wb.Sheets[1];
                    Range range = ws.Range["A1:U35"];
                    range.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap);
                    wb.Close(SaveChanges: false);
                    Marshal.ReleaseComObject(wb);
                }

                else
                {
                    Workbook wb = ExcelApp.Workbooks.Open(file);
                    Worksheet ws = (Worksheet)wb.Sheets[1];
                    Range range = ws.Range["A1:U35"];
                    range.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap);
                    wb.Close(SaveChanges: false);
                    Marshal.ReleaseComObject(wb);
                }
            }

            finally
            {
                Bitmap image = new Bitmap(System.Windows.Forms.Clipboard.GetImage());
                image.Save(ImagePath + Path.GetFileNameWithoutExtension(file) + ".svg");

                Marshal.ReleaseComObject(ExcelApp);
            }
        }


Что я уже пробовал:

private void UpdateDataOfLine1(object sender, ExecutedRoutedEventArgs e)
        {
            string[] files = Directory.GetFiles(RootPath);

            BackgroundWorker worker = new BackgroundWorker();
            worker.WorkerReportsProgress = true;
            worker.DoWork += worker_DoWork;
            worker.ProgressChanged += worker_ProgressChanged;
            worker.RunWorkerAsync();
        }



        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            string[] files = Directory.GetFiles(RootPath);

            for (int i = 0; i < files.Length; i++)
            {
                if (files[i].Contains("$") || files[i].Contains("~") || files[i].Contains("Thumb"))
                {
                    continue;
                }

                File.Copy(files[i], DestPath + Path.GetFileName(files[i]), true);

                string newFile = DestPath + Path.GetFileName(files[i]);

                ExPortRangeAsImage(newFile);

                (sender as BackgroundWorker).ReportProgress(i);
                Thread.Sleep(100);
            }
        }



        void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Status.Value = e.ProgressPercentage;
        }


        public void ExPortRangeAsImage(string file)
        {
            var ExcelApp = new Microsoft.Office.Interop.Excel.Application();

            try
            {
                if (file.Contains("BeispielDatei"))
                {
                    Workbook wb = ExcelApp.Workbooks.Open(file);
                    Worksheet ws = (Worksheet)wb.Sheets[1];
                    Range range = ws.Range["A1:U35"];
                    range.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap);
                    wb.Close(SaveChanges: false);
                    Marshal.ReleaseComObject(wb);
                }

                else
                {
                    Workbook wb = ExcelApp.Workbooks.Open(file);
                    Worksheet ws = (Worksheet)wb.Sheets[1];
                    Range range = ws.Range["A1:U35"];
                    range.CopyPicture(XlPictureAppearance.xlScreen, XlCopyPictureFormat.xlBitmap);
                    wb.Close(SaveChanges: false);
                    Marshal.ReleaseComObject(wb);
                }
            }

            finally
            {
                Bitmap image = new Bitmap(System.Windows.Forms.Clipboard.GetImage());
                image.Save(ImagePath + Path.GetFileNameWithoutExtension(file) + ".svg");

                Marshal.ReleaseComObject(ExcelApp);
            }
        }



Можете ли вы показать мне, что я делаю неправильно или как я могу это осознать?
Есть ли другие способы, кроме BackgroundWorker?

Заранее благодарю вас за вашу помощь!

[no name]

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

Member 12741482

нулевой объект возвращается буфером обмена.GetImage () и я не понимаю почему. Потому что оба метода хорошо работают, если не использовать BackgroundWorker.

1 Ответов

Рейтинг:
0

David_Wimbley

Ваша проблема заключается в том, что вы не можете получить доступ к клиповой плате из многопоточного приложения. Используя класс Thread, вы можете установить, является ли он STA или MTA...однако я не думаю, что это возможно сделать с помощью класса backgroundworker (c# - как я могу сделать фоновый рабочий поток установленным в квартиру с одним потоком? - переполнение стека[^]).

Чтобы установить STA с помощью класса Thread, вы можете сделать что-то вроде:

Thread t = new Thread(AccessClipBoardHere());
t.SetApartmentState(ApartmentState.STA);
t.Start();


Member 12741482

Спасибо Вам за это решение, но я не понимаю, как и где я должен использовать его в своем коде :(

David_Wimbley

Замените свой фоновый рабочий код кодом выше

BackgroundWorker worker = new BackgroundWorker();            
worker.WorkerReportsProgress = true;            
worker.DoWork += worker_DoWork;            
worker.ProgressChanged += worker_ProgressChanged;   
worker.RunWorkerAsync();
И вы все еще можете использовать worker_DoWork, но просто сделайте так, чтобы у него не было никаких параметров и исправьте любые ошибки компилятора из-за этого.

Member 12741482

Спасибо! Я попробую прямо сейчас...

Member 12741482

если я удалю фоновый рабочий код, если не смогу использовать worker_ProgressChanged и worker_Completeted...

David_Wimbley

Правильно,но там у вас тоже есть обходные пути. Взгляните сюда:

http://stackoverflow.com/questions/10728192/updating-a-progress-bar-in-a-c-sharp-gui-from-another-thread-and-class

Member 12741482

У меня есть вопрос по следующему коду:

Объекта methodinvoker м=нового объекта methodinvoker( ()=&ГТ; индикатор.Прогресс=ценность);
прогрессбар.вызвать(м);

progressbar-это название моего progressbar, но что такое прогресс и ценность?

David_Wimbley

Не уверен, честно говоря, я просто погуглил это link...do немного порыскайте вокруг и посмотрите, что сможете найти.