MessageBox.Show выклікаецца з Backgound работніка з ручкай асноўнага патоку карыстацкага інтэрфейсу

У мяне гэты код:

public void Blah(IWin32Window _this)
{
    for (int i = 0; i < item_quantity; i++)
    {
        try { File.Delete(item[0, i]); }
        catch (Exception ex)
        {
            if (MessageBox.Show(_this, String.Format("Error while accessing {0}\n{1}"
                , item[0, i], ex.Message), "Error", MessageBoxButtons.RetryCancel
                , MessageBoxIcon.Error) == DialogResult.Retry)
            { i--; }
        }
    }
}

... і гэты код у асноўным струмені карыстацкага інтэрфейсу:

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    AnotherClass.Blah(this);
}

Калі я выконваю гэты код, я атрымліваю небяспечнае выключэнне перакрыжаванага патоку. Што бяспечны спосаб зрабіць гэтую аперацыю?

0
лінія MessageBox.Show (...) Прыводзіць Ці памылка?
дададзена аўтар Ric, крыніца
лінія MessageBox.Show (...) Прыводзіць Ці памылка?
дададзена аўтар Ric, крыніца
Якая радок кода стварае выключэнне доступу да крос-нітка? Які тып аб'екта элемент ?
дададзена аўтар Sean Airey, крыніца

8 адказы

<�Р> Што бяспечны спосаб зрабіць гэтую аперацыю?

Там няма рэальнага бяспечнага спосабу зрабіць гэта. Акно паведамлення выскоквае з ніадкуль, без якога-небудзь прамога падлучэння да каманды, каб карыстальнік даў. Адзін від адмовы з'яўляецца тое, што карыстальнік працягвае працаваць з UI, пстрыкнуўшы мышшу або націснуўшы клавішу прабелу. І ваша акно паведамлення мілісекунды, перш чым ён націснуў мышшу або націснуў клавішу. Ён ніколі не ўбачыць паведамленне.

Так што нешта павінна было быць зроблена, гэта не было зроблена, і карыстальнік зусім не ведаюць пра гэта. Не вельмі добрая рэч. Вам трэба да лекара, ваш карыстацкі інтэрфейс, так гэта стан ніколі не можа адбыцца. Відавочна, што будзе патрабаваць, каб вы памылка справаздачнасці інакш, чым з дапамогай акна паведамлення часовага. Шматлікія магчымыя альтэрнатывы, вядома, могуць быць гэтак жа простымі, як ярлык, які паведамляе стан. StatusStrip добры для гэтага.

Фактычнае выключэнне з'яўляецца падробленай адзін. Ён запускаецца з дапамогай убудаванай дыягностыкі, якая правярае, што код выкарыстоўвае карыстацкі інтэрфейс у струменева-чынам. Базавы WinAPI выклік GetParent (), адзін з вельмі нямногіх user32 функцый Windows, якія можна смела назваць, і выкарыстоўваюцца, з працоўнага патоку. Адзіная законная прычына, я ведаю, дзе выкарыстанне Control.CheckForIllegalCrossThreadCalls працаваць вакол праблемы ў парадку. Але выправіць рэальную праблему замест гэтага.

2
дададзена
<�Р> Што бяспечны спосаб зрабіць гэтую аперацыю?

Там няма рэальнага бяспечнага спосабу зрабіць гэта. Акно паведамлення выскоквае з ніадкуль, без якога-небудзь прамога падлучэння да каманды, каб карыстальнік даў. Адзін від адмовы з'яўляецца тое, што карыстальнік працягвае працаваць з UI, пстрыкнуўшы мышшу або націснуўшы клавішу прабелу. І ваша акно паведамлення мілісекунды, перш чым ён націснуў мышшу або націснуў клавішу. Ён ніколі не ўбачыць паведамленне.

Так што нешта павінна было быць зроблена, гэта не было зроблена, і карыстальнік зусім не ведаюць пра гэта. Не вельмі добрая рэч. Вам трэба да лекара, ваш карыстацкі інтэрфейс, так гэта стан ніколі не можа адбыцца. Відавочна, што будзе патрабаваць, каб вы памылка справаздачнасці інакш, чым з дапамогай акна паведамлення часовага. Шматлікія магчымыя альтэрнатывы, вядома, могуць быць гэтак жа простымі, як ярлык, які паведамляе стан. StatusStrip добры для гэтага.

Фактычнае выключэнне з'яўляецца падробленай адзін. Ён запускаецца з дапамогай убудаванай дыягностыкі, якая правярае, што код выкарыстоўвае карыстацкі інтэрфейс у струменева-чынам. Базавы WinAPI выклік GetParent (), адзін з вельмі нямногіх user32 функцый Windows, якія можна смела назваць, і выкарыстоўваюцца, з працоўнага патоку. Адзіная законная прычына, я ведаю, дзе выкарыстанне Control.CheckForIllegalCrossThreadCalls працаваць вакол праблемы ў парадку. Але выправіць рэальную праблему замест гэтага.

2
дададзена

Я не папушчальніцтва дызайну, але вы можаце перадаць у форме да Л (), а затым Invoke() у адносінах да спасылачныя форме:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (!backgroundWorker.IsBusy)
        {
            button1.Enabled = false;
            backgroundWorker.RunWorkerAsync();
        }
    }

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        SomeClass AnotherClass = new SomeClass();
        AnotherClass.Blah(this);
    }

    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        button1.Enabled = true;
        MessageBox.Show("Done!");
    }

}

public class SomeClass
{
    public void Blah(Form frm)
    {
        int item_quantity = 5;

        for (int i = 0; i < item_quantity; i++)
        {
            try
            {
                //File.Delete(item[0, i]);

                Console.WriteLine("i = " + i.ToString());
                throw new Exception("duh");
            }
            catch (Exception ex)
            {
                frm.Invoke(new Action(() =>
                    {
                        DialogResult result = MessageBox.Show(frm, String.Format("Error while accessing {0}\n{1}", "something", ex.Message), "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                        if (result == DialogResult.Retry)
                        {
                            i--;
                        }
                    }));
            }
        }
    }
}
1
дададзена
Я не ведаю, як выкарыстоўваць функцыю Invoke LOL! Вялікі дзякуй! Ваш код працуе як шарм! =))))
дададзена аўтар Vitiaz Ryzhkov, крыніца

Я не папушчальніцтва дызайну, але вы можаце перадаць у форме да Л (), а затым Invoke() у адносінах да спасылачныя форме:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (!backgroundWorker.IsBusy)
        {
            button1.Enabled = false;
            backgroundWorker.RunWorkerAsync();
        }
    }

    private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        SomeClass AnotherClass = new SomeClass();
        AnotherClass.Blah(this);
    }

    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        button1.Enabled = true;
        MessageBox.Show("Done!");
    }

}

public class SomeClass
{
    public void Blah(Form frm)
    {
        int item_quantity = 5;

        for (int i = 0; i < item_quantity; i++)
        {
            try
            {
                //File.Delete(item[0, i]);

                Console.WriteLine("i = " + i.ToString());
                throw new Exception("duh");
            }
            catch (Exception ex)
            {
                frm.Invoke(new Action(() =>
                    {
                        DialogResult result = MessageBox.Show(frm, String.Format("Error while accessing {0}\n{1}", "something", ex.Message), "Error", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);
                        if (result == DialogResult.Retry)
                        {
                            i--;
                        }
                    }));
            }
        }
    }
}
1
дададзена
Я не ведаю, як выкарыстоўваць функцыю Invoke LOL! Вялікі дзякуй! Ваш код працуе як шарм! =))))
дададзена аўтар Vitiaz Ryzhkov, крыніца

Вы спрабуеце зрабіць працу карыстацкага інтэрфейсу на фоне патоку, а такім чынам, за выключэннем крос-нітка. RunWorkerCompletedEventArgs мае ўласцівасць называецца Памылка , які будзе ўтрымліваць любы выключэнне, якое атрымлівае кінуты RunWorkerAsync дэлегаты. Настройка апрацоўшчыка для RunWorkerCompleted на BackgroundWorker і праверыць, калі Памылка ўласцівасць мае значэнне. Калі гэта адбудзецца, падкажыце MessageBox у апрацоўшчыку, таму што вы будзеце ў патоку карыстацкага інтэрфейсу ў гэтай кропцы. Выклік BackgroundWorker <�код /> 's RunWorkerAsync метад зноў на DialogResult.Retry сцэнар.

(Вы, верагодна, прыйдзецца змяніць свой BackgroundWorker і AnotherClass.Blah , каб прыняць у значэнні I у выдатным стане вашай завесы для гэтага другога выкліку ваш BackgroundWorker . ў раздзеле DoWorkEventArgs мае ўласцівасць Аргумент , які вы можаце выкарыстоўваць, каб перадаць гэта значэнне.)

1
дададзена

Вы спрабуеце зрабіць працу карыстацкага інтэрфейсу на фоне патоку, а такім чынам, за выключэннем крос-нітка. RunWorkerCompletedEventArgs мае ўласцівасць называецца Памылка , які будзе ўтрымліваць любы выключэнне, якое атрымлівае кінуты RunWorkerAsync дэлегаты. Настройка апрацоўшчыка для RunWorkerCompleted на BackgroundWorker і праверыць, калі Памылка ўласцівасць мае значэнне. Калі гэта адбудзецца, падкажыце MessageBox у апрацоўшчыку, таму што вы будзеце ў патоку карыстацкага інтэрфейсу ў гэтай кропцы. Выклік BackgroundWorker <�код /> 's RunWorkerAsync метад зноў на DialogResult.Retry сцэнар.

(Вы, верагодна, прыйдзецца змяніць свой BackgroundWorker і AnotherClass.Blah , каб прыняць у значэнні I у выдатным стане вашай завесы для гэтага другога выкліку ваш BackgroundWorker . ў раздзеле DoWorkEventArgs мае ўласцівасць Аргумент , які вы можаце выкарыстоўваць, каб перадаць гэта значэнне.)

1
дададзена

Вам трэба выканаць код карыстацкага інтэрфейсу, як гэта пры выкліку яго з іншага струменя:

// must use invoke because the timer event is running on a separate thread
this.Invoke(new Action(() =>
{
     MessageBox.Show("Message");
}));
0
дададзена

Вам трэба выканаць код карыстацкага інтэрфейсу, як гэта пры выкліку яго з іншага струменя:

// must use invoke because the timer event is running on a separate thread
this.Invoke(new Action(() =>
{
     MessageBox.Show("Message");
}));
0
дададзена