C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

ログ内検索
  • キーワードを複数指定する場合は 半角スペース で区切ってください。
  • 検索条件は、(AND)=[A かつ B] (OR)=[A または B] となっています。
  • [返信]をクリックすると返信ページへ移動します。
キーワード/ 検索条件 /
検索範囲/ 強調表示/ ON (自動リンクOFF)
結果表示件数/ 記事No検索/ ON
大文字と小文字を区別する

全過去ログを検索

<< 0 >>
■17392  Re[1]: DataGridViewで大量データ表示中のスクロール動作
□投稿者/ ネタ好き -(2008/04/23(Wed) 12:56:21)
    No17386 (ぐっちょん さん) に返信
    これは外部設計ミスだとおもいます。
    もっと画面構成を考えて、出力列を絞った方がいいと思います。
記事No.17386 のレス /過去ログ35より / 関連記事表示
削除チェック/

■92298  スレッドをタスクで書くには
□投稿者/ TanuTanu -(2019/09/10(Tue) 11:53:12)

    分類:[VB.NET/VB2005 以降] 

    いつもお世話になっております。

    下記スレッドでは動作しました。

    Dim t As New Thread(New ThreadStart(AddressOf Form1.worker))
    t.Start()

    タスクに書き換えたいのですが方法が解りません。

    Dim _Task As Task = Task.Run(
    Sub()

    Form1.worker()

    End Sub
    )


    ご教授のほど宜しくお願いいたします。

    FORM1側***********************************

    Public Delegate Sub DATA_READ_Delegate()

    Public Sub DATA_READ()

    Debug.WriteLine(Me.DataSet1.TESTデータ.Rows(0)("TEST").ToString())

    End Sub

    Public Sub worker()

    Me.Invoke(New DATA_READ_Delegate(AddressOf DATA_READ))

    End Sub
親記事 /過去ログ159より / 関連記事表示
削除チェック/

■92299  Re[1]: スレッドをタスクで書くには
□投稿者/ WebSurfer -(2019/09/10(Tue) 12:51:41)
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92301  Re[2]: スレッドをタスクで書くには
□投稿者/ TanuTanu -(2019/09/10(Tue) 14:00:29)
    WebSurfer さん

    ありがとうございます。
    すいません小生、初心者である事を明記しておりませんでした。

    >ひょっとして、デリゲートを利用した非同期メソッドを .NET 4.5 以降で使えるようになった
    >async / await / Task を利用して書き換えたいということですか?

    はい。その通りです。

    紹介頂いた記事で解った事はasync / await / Taskを使用するばデリゲートは不要って事でした。

    冒頭で書いたコードですが、Task内でForm1のDataTableを取得すると下記エラーが出ました。

     例外がスローされました: 'System.IndexOutOfRangeException' (System.Data.dll の中)

    次にDelegateを書いてみたら、下記エラーが出ました。

     例外がスローされました: 'System.InvalidOperationException' (System.Windows.Forms.dll の中)

    どうしたらいいものか困り果てております。
    出来ましたらご教授の程宜しくお願いいたします。


記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92302  Re[3]: スレッドをタスクで書くには
□投稿者/ 魔界の仮面弁士 -(2019/09/10(Tue) 14:12:04)
    No92301 (TanuTanu さん) に返信
    >>> Debug.WriteLine(Me.DataSet1.TESTデータ.Rows(0)("TEST").ToString())
    > 例外がスローされました: 'System.IndexOutOfRangeException' (System.Data.dll の中)

    IndexOutOfRangeException とのことなので
      Me.DataSet1.TESTデータ.Rows.Count が 0 の状態で、.Rows(0) にアクセスしている
    という状況であると予想します。

    もしも TEST 列が無い場合は、ArgumentException になりそう。
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92304  Re[3]: スレッドをタスクで書くには
□投稿者/ WebSurfer -(2019/09/10(Tue) 14:30:48)
    No92301 (TanuTanu さん) に返信
    
    とりあえず取得したいデータは、
    
    Me.DataSet1.TESTデータ.Rows(0)("TEST").ToString()
    
    でよくて、非同期メソッドを使わないで(デリゲートも async/await/Task も一切使わないで)、
    普通に Form の中でそのコードを書いたら期待通り取得できるのでしょうか?
    
    そうであれば、async/await/Task を使った非同期でそのデータを取得するなら、私が紹介した
    記事のコードを例にとると、以下のようにしてみてはいかがですか?
    
    // テスト用の時間がかかるメソッド
    private string TimeCosumingMethod(DataSet dataset)
    {
        return dataset.TESTデータ.Rows(0)("TEST").ToString();
    }
    
    // async/await/Task を使った非同期呼び出し
    private async void button3_Click(object sender, EventArgs e)
    {
        this.label1.Text = await Task.Run(() => TimeCosumingMethod(this.DataSet1));
    }
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92305  Re[4]: スレッドをタスクで書くには
□投稿者/ WebSurfer -(2019/09/10(Tue) 14:52:45)
    No92304 の「テスト用の時間がかかるメソッド」のコードで VB.NET と C# がゴッチャになって
    ました。すみません。

    ×: return dataset.TESTデータ.Rows(0)("TEST").ToString();

    〇: return dataset.TESTデータ.Rows[0]["TEST"].ToString();
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92300  Re[1]: スレッドをタスクで書くには
□投稿者/ 魔界の仮面弁士 -(2019/09/10(Tue) 13:35:19)
    2019/09/10(Tue) 13:36:45 編集(投稿者)

    No92298 (TanuTanu さん) に返信
    > Public Sub DATA_READ()
    >  Debug.WriteLine(Me.DataSet1.TESTデータ.Rows(0)("TEST").ToString())
    > End Sub

    この DataSet は、UI スレッドからの読み書きが行われますか?

    Task を使うにせよ Thread を使うにせよ、
    DataSet への編集操作はスレッドセーフではないので、複数のスレッドから
    同時に読み書きが行われるのであれば、排他制御処理が必要となります。
    ※読取専用で使うのであれば、スレッドセーフが保証されている。

    基本的には、「インスタンスを生成するスレッド」と「それを利用するスレッド」が
    同一であることが望ましいです(フィールド変数ではなくローカル変数とする)。


    Task を利用するに当たり、ワーカースレッドを使うか UI スレッドを使うかを指定したい場合は、
    ContinueWith メソッドの引数に TaskScheduler インスタンスを渡すことができます。

    過去ログで言うとこのあたり。 VB ではなくて C# ですけれども…。
    http://bbs.wankuma.com/index.cgi?mode=al2&namber=68409&KLOG=116
    http://bbs.wankuma.com/index.cgi?mode=al2&namber=91647&KLOG=158
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92303  Re[2]: スレッドをタスクで書くには
□投稿者/ TanuTanu -(2019/09/10(Tue) 14:28:17)
    魔界の仮面弁士 さん

    ありがとうございます。

    実施したい内容は、下記となります。
    CSV書き込みに数秒ほど遅れる時があるのでワーカースレッドで処理させようという目論見です。

    UI スレッド:何かしらの処理 → MessageBox表示
                  ↓                      
                  ワーカースレッド:Task → Table読出し → CSVへの書き込み→UI スレッドに戻る

    この処理をしている時は複数のスレッドから同時に読み書きが行われる事はありません。

    宜しくお願いいたします。
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92308  Re[3]: スレッドをタスクで書くには
□投稿者/ TanuTanu -(2019/09/10(Tue) 15:24:29)
    WebSurfer さん

    返信ありがとうございます。

    DataSet参照渡しした後TESTデータメンバにありませんのエラーになる為、知識不足の為
    仕方なく文字列送ってみましたが System.IndexOutOfRangeException になってしまいます。
    ソースは下記となります。


    Public Function TimeCosumingMethod(ByRef STR As String)

    Debug.WriteLine(STR)

    Return True

    End Function

    Dim _Task As Task = Task.Run(
    Sub()

    Form1.TimeCosumingMethod(Form1.DataSet1.TESTデータ.Rows(0)("TEST").ToString())

    End Sub
    )
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92313  Re[4]: スレッドをタスクで書くには
□投稿者/ WebSurfer -(2019/09/10(Tue) 15:50:55)
    No92308 (TanuTanu さん) に返信

    自分は C# でしかコードは書けませんが、それで話が伝わるでしょうか?

    ダメなら VB.NET 使いの人の回答をお待ちください。
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92316  Re[3]: スレッドをタスクで書くには
□投稿者/ 魔界の仮面弁士 -(2019/09/10(Tue) 16:09:35)
    No92303 (TanuTanu さん) に返信
    > 実施したい内容は、下記となります。
    No92302 で指摘した .Rows.Count の状態はどうでしたか?


    > CSV書き込みに数秒ほど遅れる時があるのでワーカースレッドで処理させようという目論見です。
    であればフィールド変数を共用するのではなく、
    ワーカースレッドを呼び出す際に、パラメーターとして
    「DataSetのコピー」を渡すようにした方が安全かと思います。

    もしもその DataSet を DataGridView 等にバインドしている場合には、
    必ずしもスレッドセーフではなくなります。たとえば列ヘッダーのクリックや
    セル編集などといった操作によって、DataSet の状態が変更される可能性があるためです。


    > この処理をしている時は複数のスレッドから同時に読み書きが行われる事はありません。
    複数のスレッドから同時に読み込むのであれば OK ですが、
    いずれかのスレッドが書き込み中は、それを他のスレッドから読み込む事も書き込むことも NG ですね。

    DataSet をフィールド変数として共有するのであれば、
    「DataSet が編集中」であることを保証する仕組みを設けた上で、
    編集中は読み取りできないことを保証するコードを設けた方が安全です。
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92322  Re[4]: スレッドをタスクで書くには
□投稿者/ TanuTanu -(2019/09/10(Tue) 16:41:13)
    魔界の仮面弁士 さん

    返信ありがとうございます。

    カウント結果:0でした。
    スレッドでは取得できるんですがね・・・なぜなんでしょうか。

    Public Sub worker()

    Debug.WriteLine(Me.DataSet1.TESTデータ.Rows.Count)

    End Sub


    >CSV書き込みに数秒ほど遅れる時があるのでワーカースレッドで処理させようという目論見です。
    > であればフィールド変数を共用するのではなく、
    > ワーカースレッドを呼び出す際に、パラメーターとして
    > 「DataSetのコピー」を渡すようにした方が安全かと思います。

    DataSetのコピーですね。承知しました。

    宜しくお願いいたします。


記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92324  Re[5]: スレッドをタスクで書くには
□投稿者/ 魔界の仮面弁士 -(2019/09/10(Tue) 17:01:27)
    No92322 (TanuTanu さん) に返信
    > スレッドでは取得できるんですがね・・・なぜなんでしょうか。
    上記のいう「スレッド」が何を意味しているのか曖昧ですが:

    UI スレッドにとっての Me.DataSet1 と
    ワーカースレッドの Me.DataSet1 が
    別のインスタンスになっていませんか?

    とりあえず下記では、すべて「1」と表示されます。


    Public Class Form1
     Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
      Dim newRow = Me.DataSet1.TESTデータ.NewTESTデータRow()
      '
      'newRow の各列に値をセットする処理をここに記述
      '
      Me.DataSet1.TESTデータ.AddTESTデータRow(newRow)
      Me.DataSet1.AcceptChanges()
      MsgBox(Me.DataSet1.TESTデータ.Count, MsgBoxStyle.SystemModal, "Load")
     End Sub

     Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
      Task.Run(Sub() MsgBox(Me.DataSet1.TESTデータ.Count, MsgBoxStyle.SystemModal, "Button1"))
     End Sub
     Private Async Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
      MsgBox(Await Task.Run(Function() Me.DataSet1.TESTデータ.Count), MsgBoxStyle.SystemModal, "Button2")
     End Sub
    End Class
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92328  Re[6]: スレッドをタスクで書くには
□投稿者/ TanuTanu -(2019/09/10(Tue) 18:55:17)
    魔界の仮面弁士 さん

    ありがとうございました。

    別クラスでShared使っていたので、これを止めてForm1渡せば上手くいきました。

    一つ伺ってもいいでしょうか。

    ただまだ解っていないところがありまして、Timer1_Tickを使っているのですが

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

    DIM _他クラス AS NEW 他クラス(Form1)

    _他クラス=NOTHING

    End Sub

    のような使い方は、_他クラス=NOTHINGをしないと
    _他クラスのインスタンスが増殖してしまうと思っていいのでしょうか?

記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92329  Re[7]: スレッドをタスクで書くには
□投稿者/ 魔界の仮面弁士 -(2019/09/10(Tue) 20:36:13)
    2019/09/10(Tue) 21:05:58 編集(投稿者)

    No92328 (TanuTanu さん) に返信
    > 別クラスでShared使っていたので、これを止めてForm1渡せば上手くいきました。

    Shared やフィールド変数は、スレッド間で無闇に共有しないほうが良いのですけれどね。

    で… Form1 はスレッドセーフなオブジェクトではありません。
    DataSet は、読み取りに関してのみスレッドセーフが保証されていますが、
    Form のメンバーは、たとえ読み取りのみであってもスレッドセーフではありませんので、
    Form1 を非 UI スレッドに渡さないようにしてください。



    > ただまだ解っていないところがありまして、Timer1_Tickを使っているのですが
    > Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
    > DIM _他クラス AS NEW 他クラス(Form1)

    念のためにお聞きしますが、「他クラス」の中でワーカースレッドを起動して、
    その中で、引数の Form1 インスタンスを利用していたりはしないですよね?


    それはさておき、「New 他クラス(Form1)」と呼び出した場合の Form1 は、
    データ型としての Form1 クラスのことではなく、
    VB 固有の My.Forms.Form1 プロパティ相当の意味になりますよね。

    いわゆる「既定のフォーム インスタンス」などと呼ばれる機能ですが、
    この方式での Form へのアクセスは避けることを強くお奨めします。
    マルチスレッドでの開発を手がけようというのであれば。


    > のような使い方は、_他クラス=NOTHINGをしないと
    > _他クラスのインスタンスが増殖してしまうと思っていいのでしょうか?

    Nothing 代入は不要です。
    使用している変数 `_他クラス` はローカル変数なので、
    何もせずとも、End Sub 到達時点で自動的に処分されます。

    解放前に適切な終了処理が必要なもの(たとえば IDisposable など)の場合は、
    Finally 等を併用するべきですが、そうでないなら作りっぱなしで構いません。

    もし仮に、すべてのクラスが Nothing 代入を必要とするのだとしたら、
    As String な変数一つ一つにも Nothing しなければならないという事になってしまいます。


    ただ、そもそも「他クラス」のインスタンスを Tick イベントのたびに New しなおす必要が
    あるかどうかも検討してみてください。処理内容によっては、「他クラス」のインスタンスを
    フィールド変数などとして保持しておき、イベント側ではそれを使いまわすだけで十分かもしれません。
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92330  Re[8]: スレッドをタスクで書くには
□投稿者/ TanuTanu -(2019/09/10(Tue) 23:37:05)
    魔界の仮面弁士 様、WebSurfer 様

    スレッドセーフを意識して無闇にマルチスレッド多用しないように
    注意していこうと思います。

    まだまだ未熟者ではありますがこの掲示板と指導して頂ける先生方が

    居られる事でとても励みになり心の支えとなりこれからも継続して続

    けていけそうです。

    この度は本当にありがとうございました。




記事No.92298 のレス / END /過去ログ159より / 関連記事表示
削除チェック/

■92337  Re[9]: スレッドをタスクで書くには
□投稿者/ WebSurfer -(2019/09/11(Wed) 10:43:12)
    No92330 (TanuTanu さん) に返信

    このスレッドの課題は、最初の私のレスで確認させていただいた、

    > デリゲートを利用した非同期メソッドを .NET 4.5 以降で使えるようになった
    > async / await / Task を利用して書き換えたい

    だったはずですが、それは解決したのでしょうか?
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/

■92342  Re[9]: スレッドをタスクで書くには
□投稿者/ WebSurfer -(2019/09/11(Wed) 13:00:11)
    No92330 (TanuTanu さん) に返信
    
    VB.NET のコードとしてはイマイチかもしれませんが、async/await/Task を使った
    非同期メソッドのコードを貼っておきます。
    
    NorthWindProducts は Visual Studio のデータソース構成ウィザードで作った型付
    DataSet ですが、要するに質問者さんのコードの 
    
    DataSet1.TESTデータ.Rows(0)("TEST").ToString()
    
    と同様に、
    
    DataSet1.Products.Rows(0)("ProductName").ToString()
    
    で文字列を取得できると思ってください。
    
    Public Class Form3
        Dim DataSet1 As NorthWindProducts
    
        Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
            Me.Label1.Text += Await Task.Run(
                Function() As String
                    Return Me.TimeCosumingMethod(DataSet1)
                End Function
            )
        End Sub
    
        Private Function TimeCosumingMethod(ds As NorthWindProducts) As String
            System.Threading.Thread.Sleep(3000)
            Return ds.Products.Rows(0)("ProductName").ToString() &
                " + ManagedThreadId: " & System.Threading.Thread.CurrentThread.ManagedThreadId
        End Function
    
        Private Sub Form3_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            Me.DataSet1 = New NorthWindProducts
            Dim Adapter As New NorthWindProductsTableAdapters.ProductsTableAdapter
            Adapter.Fill(Me.DataSet1.Products)
    
            Me.Label1.Text = "ManagedThreadId: " &
                System.Threading.Thread.CurrentThread.ManagedThreadId & " / "
        End Sub
    End Class
記事No.92298 のレス /過去ログ159より / 関連記事表示
削除チェック/



<< 0 >>

パスワード/

- Child Tree -