Okno se zprávou, než se vykoná část kódu.   zodpovězená otázka

VB.NET

VISUAL BASIC

Zdravím,

pátral jsem na netu, ale nemužu najít srozumitelný příklad ve VB.NET (2008), předpokládám, že to nemuže být až tak složité...

Neco jako:

ShowMyMessage.show("Moment, komprimuji databazi..."
CompactDB
ShowMyMessage.close

Laboroval jsem s dalším formulářem + labelem + předáním parametru, ale label se zobrazí pouze tehdy, jestliže po nem následuje messagebox.show...

Díky za pomoc.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Pokud je nějaké okno (ať už MessageBox nebo vlastní) zobrazeno modálně, kód dále nepokračuje dokud toto okno není uživatelem uzavřeno. Naučte se základy.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

...

Kdepak jsem psal něco o modálním módu?

Nikde, že?

Pod "oknem" zcela jistě i Vy rozumíte klasický MessageBox, ale i jiný formulář s textem.

Já potřebuji ten druhý případ, .showDialog (čili modální zobrazení) znám.

Zkusíte mi poradit, nebo budete jen rýpat? :)

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Až se vyjádříte srozumitelně, možná budu moct poradit.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

No hurá...dík :)

Takže:

Je snadné před spuštěním libovolné akce (jako příklad jsem uvedl komprimace DB) zobrazit formulář s textem pro uživatele a po ukončení ho zavřít. (ne modal, to dá rozum)

Jelikož ale takových hlášení budu mít několik, potřebuju univerzální proceduru na zobrazení (třebas i formuláře)...

Logicky asi nikdo nechce mít v projektu 10 formulářu s odlišným textem.

Na problém jsem narazil, když jsem chtěl z hlavního formuláře nebo z modulu měnit LABEL.text v "univerzálním" formuláři.

Našel jsem na netu asi 7 příkladu, ale ani jeden enfunguje.

/dim fm as new frmMessage(me)...atd../

Problém je, že LABEL.text se na zobrazeném formuláři nezobrazí někdy vubec, někdy až když se program zastaví např. zavoláním MessageBoxu - to jsem jenom zkoušel, jestli vubec něc uvidím.

V prubehu vykonávaní zdrojového kódu se nezobrazí nic, jen prázdný formulář. Když použiji TextBox, ten se zobrazí, ale jako SELECT, t.j. s modrým pozadím. Zkoušel jsem u něj nastavit TabStop na false - pak se nezobrazí nic.

Několik hodin hledání a zkoušení a nic.

Dík

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Ja by som spravil úplne obyčajný formulár s jedným label, prípadne ďalšie prvky. U nich v design móde nastavte Modifier na Private. Potom do kódu pridáte Public vlastnosti, ktoré sprístupňujú napríklad Label.Text .Podľa kontextu niektoré iba na čítanie. Pred dlhotrvajúcim príkazom vytvoríte novú inštanciu takéhoto formulára, nastavíte potrebné vlastnosti, až tak zzobrazíte pomocou Show(), urobíte, čo treba a zničíte ten formulár(.Dispose()).Premenná s tým formulárom by mala byť na úrovni metódy, aby ju Garbage Collector odstránil po opustení metódy. Alebo môžete použiť blok kódu using.

Taktiež zvážte použitie BackgroundWorkeru, pokiaľ sa hodí.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To všecho jsem zkoušel.

Resp. jsem zkoušel Public property, přirazoval jsem pak hodnotu label.text, atd.

Nefunguje.

Akorát jsem nenastavoval Modiefier na Private, to se nikde neuvádělo.

Ja tu hodnotu umím změnit několika zpusoby, ale v prubehu vykonávání kódu se prostě nezobrazí...

Už jsem zkoušel hodně příkladu...

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Napíšte kód aspoň jedného spôsobu, ktorý ste skúšali a nefungoval Vám.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

toto je "message formular"

Public Class frmStatus
       Inherits System.Windows.Forms.Form
	   
    Private _hlaseni As String

    Public Property Hlaseni() As String
        Get
            Return _hlaseni
        End Get
        Set(ByVal value As String)
            _hlaseni = value

        End Set
    End Property

    Public Sub New()

        ' This call is required by the Windows Form Designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        LABEL1.Text = Hlaseni

    End Sub
End Class

A tady volam zobrazeni:

Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim msg As String = "Moment, komprimuji databazi..."
        Dim fm As New frmStatus

        fm.Hlaseni = msg
        fm.Show()        
        CompactDB()        
        fm.Dispose()
    End Sub

Behem komprimace (ale treba i ukladani dat do DB) zobrazi frmStatus, ale prazdný.

Až po ukončení kódu se zobrazí - to když volám další messagebox o úspěšném/neúspěšném uložení, nebo komprimování.

Dukaz...:

http://uploading.sk/?v=vb1.png

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Och môj bože! Nastavíte do private premennej text, ktorý chcete zobraziť v Label, a do Label.Text priradíte v konštruktore. Jasné, že Vám to zobrazí prázdny Label. _hlaseni dajte úplne preč, je nežiadúca. A vlastnosť Hlaseni napojte priamo na vlastnosť Text Labelu. Takýmto spôsobom sa zverejňujú vlastnosti ovládacích prvkov, nie cez private premennú, ktorej hodnotu v konštruktore priradíte ovládaciemu prvku. Prečo? Pretože môžete 1000x zmeniť vlastnosť Hlaseni a tým premennú _hlaseni, ale do Label1.Text sa to nepremietne, nemá kde.

Inak, aj premenná msg je zbytočná, ten reťazec v "" môžete priradiť aj priamo do Hlaseni, ale to už je len taký detail.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Hm, tak promenna msg je fakt nepodstatna, zbyla tam z jinych verzi, proto jsem ji narychlo pouzil, abych mohl dat k dispozici zdrojak.

Fajn, takze zase nic.

To, co jste napsal, jsem mel jako prvni moznost - primo v SET vlastnosti nastaven label.text, zas tak blbej nejsem :)

Jenomze jak jsem jiz napsal - na netu je tolik ruznych verzi, ze to ZREJME nebude trivialni zalezitost...

Vysledek - NEFUNGUJE TO.

Formular frmStatus:

Public Property Hlaseni() As String
        Get
            Return LABEL1.Text
        End Get
        Set(ByVal value As String)
            LABEL1.Text = value
        End Set
    End Property

volani z události btn:


    Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click        
        Dim fm As New frmStatus

        fm.Hlaseni = "Moment, komprimuji databazi..."
        fm.Show()
        CompactDB()
        fm.Dispose()
    End Sub

Takhle to vypada, kdyz ukladam data:

http://uploading.sk/images/vb2.png

A takhle po ukonceni zapisu dat:

http://uploading.sk/images/vb3.png

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Ja som použil následovný kód, a až na to, že je to sprasené a na pár ďalších blbostí to funguje.

/*Main form*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

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

        private void button1_Click(object sender, EventArgs e)
        {
            t = new System.Threading.Thread(new System.Threading.ThreadStart(Thread));
            t.Start();                
        }
        MessageForm frm = new MessageForm();
        System.Threading.Thread t;
        private void ShowMessageWindow(string text)
        {
            if (this.InvokeRequired) this.Invoke(new Action<string>(this.ShowMessageWindow), text);
            else
            {
                frm.MessageText = text;
                frm.Show();
            }   
        }
        private void HideMessageWindow()
        {
            if (this.InvokeRequired) this.Invoke(new Action(this.HideMessageWindow));
            else
            {
                frm.Hide();
            }
        }
        private void Thread()
        {
            ShowMessageWindow("Please wait...");
            System.Threading.Thread.Sleep(5000);
            HideMessageWindow();
        }
    }
}
/*Message form*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WinSandbox
{
    public class MessageForm : Form
    {
        private Label lbl;
        public string MessageText
        {
            get
            {
                return lbl.Text;
            }
            set
            {
                lbl.Text = value;
            }
        }
        public MessageForm(string initialText)
        {
            this.Text = "Message Form";
            this.SetClientSizeCore(320, 240);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
            lbl = new Label();
            lbl.Location = new Point(20, 20);
            lbl.AutoSize = true;
            lbl.Text = initialText;
            this.Controls.Add(lbl);
        }
        public MessageForm() : this("Default message") { }
    }
}

Berte však do úvahy, že ten kód som písal na rychlo a preto môže byť dosť sprasený a tiež nie je dotiahnutý do dokonalosti. Taktiež ak to je možné, mali by ste vyskúšať BackgroundWorker.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

hm, tak dik... :)

cecko neumim,,,

Diky za snahu.

P.S. Jestli to ale dobre ctu, tak v ukazce je volane okno PLEASE WAIT... a po 5 vterinach zmizi...

No tak to umim taky. Ja potrebuji, aby zustalo otevrene (show), a mezitim se zpracovaval kod.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

To okno se nevykreslí, protože vlákno aplikace je plně vytíženo zpracováváním procedury CompactDB(). Aby se vykreslilo, musíte ji volat v novém vlákně.

např.

 Imports System.Threading

Public Class Form1

    Private wh As AutoResetEvent = New AutoResetEvent(False)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Using formular As New Form2
            formular.Label1.Text = "Dlouho trvající akce. Čekejte."
            formular.Show()
            Dim vlakno As Thread = New Thread(AddressOf Me.Akce)
            vlakno.Start()
            wh.WaitOne()
        End Using
    End Sub

    Private Sub Akce()
        Thread.Sleep(5000)
        wh.Set()
    End Sub
End Class

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Asi jiná cesta není, taky jsem nakonec usoudil, že bude nutné vlákno...

Díky za ochotu.

:)

ACH BOZE...

Zkusil jsem, ale normalne nechapu:

1. label se nevypise (jako predtim - prazdny form, bez labelu)

2. po vypsani msgboxu o ukonceni - label se na pozadi vypise

3. frmStatus se z pameti nezmaze, vse zustane otevrene a zasekle...

asi kvuli wh.WaitOne()

:)

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Do procedúry Thread môžete dať úplne hocičo. To čakanie 5 minút bol príklad dlhotrvajúcej činnosti, pokiaľ chcete použiť ten kód, kľudne tam dajte volanie CompactDB.

Ale:

1) Ten kód nie je napísaný úplne ideálne

2) Ak budete čokoľvek z UI meniť v CompactDB alebo funkciach, ktoré voláte, musíte to meniť v UI vlákne, vytvorte si na ten účel funkciu podobnú tej ShowMessageWindow. Tzn. Ak this.InvokeRequired zavoláte this.Invoke a predáte tomu delegát zodpovedajúci tej istej funkcii a tie isté parametre, metóda Invoke sa postará o volanie tej funkcii z UI vlákna a potom už InvokeRequired v tom istom kóde vráti false, v tom prípade vykonáte, čo je potrebné.

Inak, je to v C#, takže až na niektoré detaily to môžete previesť nejakým konvertorom, napr. http://www.developerfusion.com/tools/con... .

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tak pozerám, že p. Herceg už napísal iný kód, použite ten jeho, pokiaľ to bude možné.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To nevadi, kazdy napad se ceni.

Musim prostudovat vsechny moznosti a zvolit tu nejoptimalnejsi.

Jeste jednou diky.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Poviem to takto: Pokiaľ Vám ide len o funkčnosť, tak môžete použiť aj moju verziu, ale ak Vám ide aj o správnosť použitia, tak lepšie je na tom kód p. Hercega, ako inak. Neskôr sa Vám môže vyplatiť, ak použijete jeho spôsob. Nie som úplný začiatočník, ale môžem s istotou povedať, že na p. adminov nemám. Ani na p. Linharta.

nahlásit spamnahlásit spam 0 odpovědětodpovědět
 Private Sub Button1_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim fm As New frmStatus

    fm.Hlaseni.Text = "Moment, komprimuji databazi..."
    fm.Show()
    Application.DoEvents() ' když holt nechcete použít vlákno
    CompactDB()
    fm.Dispose()
  End Sub

Co by provedlo Application.DoEvents() ???

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nic. DoEvents pouze vynuceně zpracuje frontu čekajících Windows událostí.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nic? Zkusil jsem to (Form1 s Button1, frmStatus s Label1 a výše uvedeným kódem). Bez DoEvents se label nedokreslí, text se nevypíše. S DoEvents je label kompletní a akce proběhne dle očekávání.

Netvrdím, že je to správně, jen uvádím výsledek svého pokusu v Visual Basic 2010 Express.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

To jo, ono se to překreslí, jenže neřeší to původní problém - aplikace bude třeba 15 sekund ve stavu neodpovídá, prostě bude zamrzlá, dokud se akce nedokončí.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Pochopitelně. To je důsledek vyřízení těch čekajících zpráv. Až se tyto vyřídí, uživatelské rozhraní zamrzne znovu, dokud nebude uvolněno hlavní vlákno. Pokud se nějaká dlouhotrvající operace provádí v cyklu, lze vždy na konci cyklu zavolat DoEvents a tím částečně zprovoznit UI, to je ovšem naprosto dobytčí postup a práce s takovou aplikací se bude rovnat hraní Doom 3 na 80386.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Problém je v tom, že metoda CompactDB se spouští v hlavním vlákně. Nově vytvořené okno se nemůže překreslit, dokud neskončí obsluha události, tudíž se nevykreslí ani Label.

Doporučuji si napsat takovouto obecnou funkci, která provede předanou metodu v jiném vlákně a přitom zobrazí okno. Píšu to z hlavy, takže to možná není úplně správně, ale to si už doděláte.

Fungovat to bude v .NET 4, pro starší verze by se to muselo mírně upravit.

Public Sub LongOperation(text As String, fn As Action)
    'zobrazit okno
    Dim sw = New StatusWindow(text)
    sw.Show()

    'spustit úkol v novém vlákně
    Dim sc = System.Threading.SynchronizationContext.Current
    Task.Factory.StartNew(
        Sub()
            Dim _exception As Exception
            Try
                'spustit předanou funkci
                fn()
            
            Catch ex As Exception
                'zaznamenat případnou výjimku
                _exception = ex
            End Try

            'schovat okno (je nutné přes synchronizationContext, abychom na něj nesahali z jiného vlákna)
            sc.Post(
                Sub(s)
                    'schovat okno
                    sw.Close()
                    
                    'pokud byla výjimka, zobrazit messagebox
                    If _exception IsNot Nothing
                        MsgBox(_exception.Message)
                    End If
                End Sub, Nothing
            )
        End Sub
   )
End Sub

Použití pak vypadá takhle:

Protected Sub Button1_Click( ...

    LongOperation("Komprimuji databázi",
	    Sub()
		    CompressDB()
		End Sub
	)

End Sub

Ideální by bylo to zapouzdřit do nějaké třídy LongRunningTask, metodě LongOperation byste předal objekt dědící z nějaké třídy LongRunningTask, který by měl implementovanou nějakou metodu.

Hodit se to bude ve chvíli, kdy budete chtít dávat z funkce fn do okna StatusWindow informace, např. kolik procent je již hotovo, nebo měnit text v titulku. Třída LongRunningTask může mít definovanou

např. událost ProgressChanged a okno na ni může nějak reagovat.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tomáši, díky. Snažím se všechno zatím dělat pro frame 2.0, s ohledem na adresáta.

Tvuj nápad je zajímavý, zkusím se s tím pohrát - snad to předělám.

Ještě jednou dík kluci.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Pro převod do .NET 2.0 je potřeba následující:

1. Všechny vnořené funkce vyčlenit vně této metody a nějak pojmenovat. Ve funkcích, kde se používaly, na ně odkázat přes AddressOf:

něco(Sub()
     ...
     End Sub)

změnit na

něco(AddressOf Funkce1)
...
Private Sub Funkce1()
...
End Sub

2. Task Parallel Library v .NET 2.0 není, ale můžeme Task nahradit pomocí vlákna:

Task.Factory.StartNew(AddressOf Funkce1)

změnit na

Dim t As New Thread(AddressOf Funkce1)
t.Start()

3. A místo předané proměnné fn typu Action je třeba předat delegát, něco jako:

Public Delegate Sub LongOperationDelegate()
...
Public Sub LongOperation(title As String, fn As LongOperationDelegate)
...
End Sub

Jestli se nepletu, to by mělo být vše.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Tomasi,

zkusil jsem si ten prvni priklad, pro NET4 funguje bezvadne.

Kdyz jsem to ale chtel pro NET2.0, tak to samozrejme neslo, protoze nelze pouzit jako parametr proceduru (typ Action)

Tak jsem to nahradil pres BackgroundWorker.

Nyni jsem chtel pouzit tento priklad, ale mam zasadni problem:

V NET 2.0 nemuzu imporotovat System.Threading.Task.

Nelze pouzit Task.

Neni chyba ve mne? :)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Promin, spatne jsem to precetl.

Jdu to zkusit, zatim dik.

...

Takze

Public Sub LongOperation(title As String, fn As LongOperationDelegate)
...
End Sub

Ted nevim, co mam pri volani teto procedury pouzit jako parametr...

  LongOperation("Komprimuji databazi, moment...", ?????)

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Přečtěte si pořádně můj předchozí příspěvek - Task v .NET 2.0 není, je to novinka v 4.0. Použijte Thread.

A místo Action dejte Delegate, o tom jsem psal taky výše.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Vzdyt jsem se omluvil kvuli TASK.

Prehledl jsem to.

Ale to Delegate nechapu.

Misto Action dam Delegate, ale pak vlastne volam

LongOperation s parametrem TEXT a LongOperationDelegate?

Nerozumim...

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Aha, přehlédl jsem to.

Delegát je datový typ funkce.

Vy si nejdřív nadeklarujete typ LongOperationDelegate přes tu deklaraci

Public Delegate Sub LongOperationDelegate()

Tím říkáte, že typ LongOperationDelegate reprezentuje funkci, která nic nevrací (je tam Sub) a nebere žádné parametry (prázdné závorky).

Pak nadeklarujete funkci LongOperation s prvním parametrem typu string (text v okně) a druhým parametrem typu LongOperationDelegate (tedy procedura bez parametrů).

Při volání téhle funkce dáte do druhého parametru AddressOf název_funkce a je to, VB.NET to automaticky zkonvertuje na delegáta daného typu.

Stačí takto?

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět

Omlouvam se, ale nejak jsem se zacyklil.

Mohu poprosit o konkretni ukazku?

Nemuzu z toho vybruslit.

Napsal jsem to takto:

 Public Delegate Sub LongOperationDelegate()

    Public Sub LongOperation(txt As String, fn As LongOperationDelegate)
        Dim sw = New frmSTATUS 'okno s hlasenim
        sw.Hlaseni = txt  'tady jenom nastavim vlastnost Hlaseni, pres kterou zmenit text v okne
        sw.Show()        
    End Sub

pak jsem si zapsal SUB, kde volam komprimaci

Public Sub PROCEDURA1()
        Dim t As New Thread(AddressOf CompactDB)
        t.Start()                
    End Sub

A zkousim to volat po udalosti Click:

Private Sub Button1_Click_1(sender As System.Object, e As System.EventArgs) Handles Button1.Click

        LongOperation("Moment prosim, komprimuji databazi.", AddressOf PROCEDURA1)

    End Sub

A nic.

Neco jsem asi po...

Upresnim:

Okno s hlasenim se objevi a zustane tam naveky.

A aby se to nepletlo, tak s databazi se nic nedeje.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Až po to PROCEDURA1 je to dobře - Thread už máte v té funkci LongOperation.

Tady by mělo stačit:

LongOperation("Moment...", AddressOf CompactDB)

CompactDB už je procedura bez parametrů.

Anebo pokud chcete volat PROCEDURA1, tak dovnitř dejte jen:

Private Sub PROCEDURA1()
   CompactDB()
End Sub

O spouštění na pozadí a zobrazení okna se stará už ta LongOperation, v té funkci dáte jen ten kód, který chcete spustit na pozadí.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Kdyz ono to tak hezky vypada...

A nefunguje :(

Okno se zobrazi, ale komprimace se nespusti.

To bych poznal - mam osetreny msg vystup jak v pripade chyby, tak v pripade uspesne komprimace.

Nemuze to byt zpusobene tim, ze komprimace je funkce, ktera vraci bud true nebo false (v zavislosti od uspesnosti?)

V pripade Backgroundworkeru to chodilo, takze v procedure samotne chyba neni.

Predtim jsem ji volal

if CompactDB then
end if

nahlásit spamnahlásit spam 0 odpovědětodpovědět

A nemáte špatně tu funkci LongOperation? Pošlete sem celý kód.

Pokud CompactDB vrací hodnotu, tak musíte jít přes to PROCEDURA1 a ComapactDB volat až z ní.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ano, hned mne to napadlo, a volal jsem to radeji pres testovaci PROCEDURA1.

Nepomohlo.

Takze nyni mam:

    Public Delegate Sub LongOperationDelegate()

    Public Sub LongOperation(txt As String, fn As LongOperationDelegate)
        Dim sw = New frmSTATUS
        sw.Hlaseni = txt
        sw.Show()
    End Sub

   Public Sub PROCEDURA1()
        Message.Show ("procedura1")
        If CompactDB() Then
        End If
    End Sub

a volam to pres:

 Private Sub Button1_Click_1(sender As System.Object, e As System.EventArgs) Handles Button1.Click
        LongOperation("Moment prosim, komprimuji databazi.", AddressOf PROCEDURA1)
    End Sub

Melo by to fungovat, ale nefunguje.

Spusti se okno s hlaskou, ale NEPROVEDE se ani PROCEDURA1, a logicky ani CompactDB.

Pro jistotu jsem na zacatek procedur dal message.

Nic.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Tu LongOperation máte pochopitelně blbě - ta musí dělat to samé, co dělala původní implementace pro .NET 4. Otevřít okno, schovat si někam synchronizationContext, vytvořit nové vlákno, v něm spustit předaného delegáta a po dokončení zase to okno přes ten synchronizationContext zavřít.

Vyjděte z původního kódu pro .NET 4.0, vnořené funkce vykopírujte do samostatných funkcí a odkažte se na ně přes AddressOf.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Dik za reakci, ale to fakt nechapu.

Vzdyt parametr fn obsahuje AddressOf procedury (PROCEDURA1).

Nechapu, jake vlakno mam jeste volat...

Poprosil bych ukazku, jestli muzu.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Vy tam žádné vlákno nevoláte, nikde tam nemáte proměnnou typu Thread atd. Ten parametr fn sice ve funkci LongOperation máte, ale nikde ho nepoužíváte - jen otevřete okno a zobarazíte. Tu metodu LongOperation nemáte celou podle toho příkladu, co jsem uváděl.

Private _longOperationSyncContext As SynchronizationContext
Private _longOperationWindow As StatusWindow

Public Sub LongOperation(text As String, fn As LongOperationDelegate)
    'zobrazit okno
    _longOperationWindow = New StatusWindow(text)
    _longOperationWindow.Show()

    'spustit úkol v novém vlákně
    _longOperationSyncContext = SynchronizationContext.Current
    Dim t As New Thread(AddressOf LongOperationWork, fn)
    t.Start()
End Sub

Private Sub LongOperationWork(state As Object)
    Dim fn As LongOperationDelegate = CType(state, LongOperationDelegate)
    Dim _exception As Exception
    Try
        'spustit předanou funkci
        fn()
    
    Catch ex As Exception
        'zaznamenat případnou výjimku
        _exception = ex
    End Try

    'schovat okno (je nutné přes synchronizationContext, abychom na něj nesahali z jiného vlákna)
    _longOperationSyncContext.Post(AddressOf LongOperationFinish, Nothing)
End Sub

Private Sub LongOperationFinish(state As Object)
    'schovat okno
    _longOperationWindow.Close()
            
    'pokud byla výjimka, zobrazit messagebox
    If _exception IsNot Nothing
        MsgBox(_exception.Message)
    End If
End Sub
nahlásit spamnahlásit spam 0 odpovědětodpovědět

hm, nejde to spustit, protoze:

Error 1 Overload resolution failed because no accessible 'New' can be called with these arguments:

'Public Sub New(start As System.Threading.ParameterizedThreadStart, maxStackSize As Integer)': Value of type 'Projekt.modFunke.LongOperationDelegate' cannot be converted to 'Integer'.

'Public Sub New(start As System.Threading.ThreadStart, maxStackSize As Integer)': Method 'Private Sub LongOperationWork(state As Object)' does not have a signature compatible with delegate 'Delegate Sub ThreadStart()'.

'Public Sub New(start As System.Threading.ThreadStart, maxStackSize As Integer)': Value of type 'Projekt.modFunke.LongOperationDelegate' cannot be converted to 'Integer'. f

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět

Psal jsem to z hlavy, nahraďte v metodě LongOperation poslední dva řádky takto:

    Dim t As New Thread(AddressOf LongOperationWork)
    t.Start(fn)

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jo, ten parametr se mu nelíbil, jenom jsem nevedel, co s nim...

Teda Tomasi, klobouk dolu.

Diky moc, fakt.

Tenhle problem mam uz dost dlouho a musel jsem ho resit pokazde nejakou oklikou.

Funguje, jeste jednou dik.

nahlásit spamnahlásit spam -1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback