トップページ > 記事閲覧
非同期ロードが終わらない
名前:keen 日時: 2018/02/13 18:51

お世話になります。 先日のコーデック関連の件ではお騒がせしました。 その後GetMovieImageSize_Fileの件で頂いたバイナリを用いて開発を続けておりましたが、非同期読み込みをONにした状態で読み込みを行った際にCheckHandleASyncLoadがTRUE(=1)しか返さずに読み込みが終わらないという状況が発生しました。 コーデックの件で貼っていただいたバイナリでも試しましたが状況は同じでした。 ttp://dxlib.o.oo7.jp/cgi/patiobbs/patio.cgi?mode=view&no=4310 コード全てを貼ることができないのですが、問題は以下のようなコード(VB.net)で発生しています。 こちらに資産として残っているVBのコードではProcessMessage()を行っていないように見えたので、この有無でも検証を行いましたが解決できませんでした。 読み込み時: DX.SetUseASyncLoadFlag(DX.TRUE) handle = DX.LoadGraph(MWButtonToTempFolderPath(tag) & _FileName, DX.TRUE) 'ハンドル取得 DX.SetUseASyncLoadFlag(DX.FALSE) 使用時: DX.ProcessMessage() MsgBox(DX.CheckHandleASyncLoad(handle)) 起動時の指定オプション: '解像度と色深度設定 DX.SetGraphMode(screen.Bounds.Width, screen.Bounds.Height, 32) '描画ウィンドウの位置を設定 DX.SetWindowInitPosition(screen.Bounds.X, screen.Bounds.Y) 'ウィンドウモード(枠無し)で起動 DX.ChangeWindowMode(DX.TRUE) DX.SetWindowStyleMode(2) 'ウィンドウがアクティブじゃない時も処理を続ける DX.SetAlwaysRunFlag(DX.TRUE) 'DxLib_Init()を呼んだwindow以外からも操作を可能にする DX.SetMultiThreadFlag(DX.TRUE) '透過チャンネルを有効に設定 DX.SetMovieColorA8R8G8B8Flag(DX.TRUE) '一度裏画面に描画を行い、Flipすると描画が行われるように設定(ダブルバッファリング) DX.SetDrawScreen(DX.DX_SCREEN_BACK) '2枚以上の画面にScreen.flipする場合デフォルトではVSync待ちで遅くなるのでVSyncは切る DX.SetWaitVSyncFlag(DX.FALSE) '多分これが無いとプログラム本体のIME関連動作がおかしくなる DX.SetUseIMEFlag(DX.TRUE) '開発したPCの環境ではこれを使わないとAccessViolationで落ちる DX.SetUseMediaFoundationFlag(DX.FALSE) 調べても原因になりそうなものを見つけられなかったのですが、非同期読み込み指定時には何か他の処理も必要なのでしょうか? よろしくお願いします。
メンテ

Page: 1 |

Re: 非同期ロードが終わらない ( No.1 )
名前:管理人 日時:2018/02/15 01:21

非同期読み込みをした場合は CheckHandleASyncLoad の戻り値が FALSE になるまで待つ必要があるのですが、 何時まで経っても FALSE にならないということでしょうか? SetUseASyncLoadFlag(TRUE); int handle = LoadGraph( FileName ); SetUseASyncLoadFlag(FALSE); while( ProcessMessage() == 0 ) { if( CheckHandleASyncLoad( handle ) == FALSE ) { // 読み込みが完了したらループを抜ける break ; } }
メンテ
Re: 非同期ロードが終わらない ( No.2 )
名前:keen 日時:2018/02/15 10:14

>何時まで経っても FALSE にならないということでしょうか? その通りです。1分2分と放置してもずっとTRUEを吐き続けています。-1にもFALSEにもなりません。 検証コードは以下の部分をWhile文で回していましたが、書くのを忘れていました。申し訳ありません。 使用時: DX.ProcessMessage() MsgBox(DX.CheckHandleASyncLoad(handle))
メンテ
Re: 非同期ロードが終わらない ( No.3 )
名前:管理人 日時:2018/02/16 00:47

> 検証コードは以下の部分をWhile文で回していましたが、書くのを忘れていました。申し訳ありません。 > 使用時: > DX.ProcessMessage() > MsgBox(DX.CheckHandleASyncLoad(handle)) すみません、MsgBox とは、メッセージボックスを表示する機能でしょうか? もしそうだとしますと、メッセージボックスは『OK』や『Cancel』などのボタンを押さないと消えないと思うのですが この処理を While文でループするということでしょうか・・・? 1回のループを回すのにメッセージボックスの『OK』や『Cancel』などのボタンを押さなければならないとしますと なかなか非同期読み込み処理が終わらないかもしれません、というのも、どうしてもメインスレッドで行わなければならない処理は ProcessMessage の中で処理されるので、非同期読み込み処理を完了させるまでには何度か ProcessMessage を呼ばなければならないので・・・
メンテ
Re: 非同期ロードが終わらない ( No.4 )
名前:keen 日時:2018/02/16 01:11

ええっと、説明が悪くて申し訳ありません。 >もしそうだとしますと、メッセージボックスは『OK』や『Cancel』などのボタンを押さないと消えないと思うのですが >この処理を While文でループするということでしょうか・・・? この部分は非同期ロードが終わらない事象を確認してから加えた部分です。 Thread.Sleepなどの後に呼び出すなど幾つか読み出しを待つ処理を加えたり、提示して頂いたようなFALSEが返らない間何もしないWhile文を加えてProcessMessageを行うような処理を行っても非同期読み出しは終了しませんでした。 もう一度書き直しましたが(VBで申し訳ありません)、以下のような処理でCheckHandleASyncLoad(handle)がFALSEになるのを待っても、ずっとTRUEしか返ってこないという状況です。 DX.SetUseASyncLoadFlag(DX.TRUE) handle = DX.LoadGraph([ファイルパス]) 'ハンドル取得 DX.SetUseASyncLoadFlag(DX.FALSE) While DX.CheckHandleASyncLoad(handle) <> DX.FALSE DX.ProcessMessage() End While
メンテ
Re: 非同期ロードが終わらない ( No.5 )
名前:管理人 日時:2018/02/17 01:57

すみません、ProcessMessage と CheckHandleASyncLoad を使ったループは試されていたのですね 手元のバージョンでは問題なく非同期読み込みを実行することができたのですが、以前 keenさんに お渡ししたバージョンでは非同期読み込みが正常に実行できませんでした そして、すみません、失念していたのですが以前 keenさんに暫定最新版をお渡ししたあと 動画ファイルの非同期読み込みが正常に行えないバグが発覚して、修正したのでした 現在の暫定最新バージョンでは正常に非同期読み込みを行うことができますので、 お手数で申し訳ありませんが再度こちらをダウンロードしてください m(_ _;m https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用
メンテ
Re: 非同期ロードが終わらない ( No.6 )
名前:keen 日時:2018/02/17 13:07

返信ありがとうございます。 頂いたバイナリについて以下のコードで確認を行いましたが、音楽については正常に非同期ロードが行えるものの、やはり動画・画像については非同期読み込みが完了せず、ループを抜けることが出来ない状態でした。 If isAsyncLoad Then '非同期ロード待ち   While DX.CheckHandleASyncLoad(handle) <> DX.FALSE DX.ProcessMessage() End While isAsyncLoad = False End If
メンテ
Re: 非同期ロードが終わらない ( No.7 )
名前:774 日時:2018/02/17 19:36

VB.NET、フォームなしで、動画をASyncで読み、再生し、終了する というコードを書いて見ました。 参照は DxLibDotNet.dll の方です。(Unicode版は SetUseMediaFoundationFlag が無い?ようなので) ただし自環境では  SetUseMediaFoundationFlag(DX.FALSE) ... MP4を再生できない  SetMovieColorA8R8G8B8Flag(DX.TRUE) ... AVI(DivX), OGV以外でクラッシュする(MPEG1、MP4 など) のため、いずれもコメントアウトしています。 ※αチャネル付き動画は持っていないので未検証です。 Imports DxLibDLL Module Module1 Sub Main() DX.SetGraphMode(640, 480, 32) DX.ChangeWindowMode(DX.TRUE) ' DX.SetUseMediaFoundationFlag(DX.FALSE) If DX.DxLib_Init() < 0 Then GoTo EXIT_PROC ' DX.SetMovieColorA8R8G8B8Flag(DX.TRUE) DX.SetDrawScreen(DX.DX_SCREEN_BACK) Dim r, data_handle, ct DX.SetUseASyncLoadFlag(DX.TRUE) data_handle = DX.LoadGraph(てきとーな動画ファイル) DX.SetUseASyncLoadFlag(DX.FALSE) ct = 0 Do ' 読んでいる間、カウンターでも表示しよう ct = ct + 1 r = DX.CheckHandleASyncLoad(data_handle) DX.ClearDrawScreen() System.Threading.Thread.Sleep(1) DX.DrawString(8, 8, "Count = " + ct.ToString(), DX.GetColor(255, 255, 255)) DX.ScreenFlip() If DX.ProcessMessage() = -1 Then GoTo EXIT_PROC Loop While r = DX.TRUE Dim bOK As Boolean bOK = True DX.PlayMovieToGraph(data_handle) Do DX.DrawExtendGraph(0, 0, 640, 480, data_handle, DX.FALSE) DX.ScreenFlip() DX.WaitTimer(1) If DX.GetMovieStateToGraph(data_handle) <> 1 Then bOK = False If DX.ProcessMessage() = -1 Then bOK = False Loop While bOK = True EXIT_PROC: If DX.DxLib_IsInit() = DX.TRUE Then DX.DxLib_End() End Sub End Module
メンテ
Re: 非同期ロードが終わらない ( No.8 )
名前:管理人 日時:2018/02/18 02:00

うーん謎ですね・・・ 手元の環境で正常に動作することを確認した以下の C# のプログラムをビルドして作成した実行ファイルを こちらにアップしましたので、よろしければ keenさんの環境でも正常に動作するかお試しいただけないでしょうか? m(_ _;m https://dxlib.xsrv.jp/temp/ASyncLoadDotNetTest.zip using System; using DxLibDLL; namespace DxLibDLLTest { static class Program { [STAThread] static void Main() { // ウィンドウモードで起動 DX.ChangeWindowMode( DX.TRUE ); // 背景をグレーにする DX.SetBackgroundColor( 128,128,128 ); // DXライブラリの初期化 if( DX.DxLib_Init() < 0 ) { return; } // Test2.bmp を非同期読み込み DX.SetUseASyncLoadFlag( DX.TRUE ); int GraphHandle = DX.LoadGraph( "Test2.bmp" ) ; DX.SetUseASyncLoadFlag( DX.FALSE ); // 読み込み完了を待つ while( DX.ProcessMessage() == 0 ) { if( DX.CheckHandleASyncLoad( GraphHandle ) == DX.FALSE ) break; } // 描画先を裏画面にする DX.SetDrawScreen( DX.DX_SCREEN_BACK ); // メインループ while( DX.ProcessMessage() == 0 ) { // 画面に Test2.bmp を描画する DX.ClearDrawScreen() ; DX.DrawGraph( 0, 0, GraphHandle, DX.TRUE ) ; DX.ScreenFlip() ; } } } } > 774さん 載せていただいたコードを C#言語にした書き換えて実行してみましたが、正常に動作しました 774さんの環境では正常に動作しない、ということでしょうか? > 参照は DxLibDotNet.dll の方です。(Unicode版は SetUseMediaFoundationFlag が無い?ようなので) Unicode版にも SetUseMediaFoundationFlag はありますが・・・ ご覧になっているバージョンの更新日時はどのようになっていますでしょうか?
メンテ
Re: 非同期ロードが終わらない ( No.9 )
名前:774 日時:2018/02/18 03:51

> 774さんの環境では正常に動作しない、ということでしょうか? > ... > Unicode版にも SetUseMediaFoundationFlag はありますが・・・ すみません、前者は「これは動きました」という意味で書きました。後者は.vbprojを再確認すると 参照が旧バージョンのファイルをさしていましたので、設定し直して問題ないことを確認いたしました。 お手数をおかけしました。
メンテ
Re: 非同期ロードが終わらない ( No.10 )
名前:keen 日時:2018/02/18 21:24

>管理人様 返信が遅れました。 提示していただいたプログラムについては正常に動作することを確認しました。 自分の作っているプログラムではメインのフォームと描画用スレッドを持ち、そこでDxLib関連の処理を行うという構造になっているので、問題はそこに有るのかもしれません。 一旦問題を再現できるプログラムを作成した後に返信を行います。
メンテ
Re: 非同期ロードが終わらない ( No.11 )
名前:keen 日時:2018/02/18 22:05

>774様 申し訳ありません、返信を忘れていました。 こちらでも動作を確認できましたが、やはり自分のプログラムでは動作しないという状況です。 >管理人様 サンプルの作成をし、メールでプロジェクトを送信しました。 内容はメールに添付したとおりですが、こちらにもプログラムを載せます。 内容としては、ロードと同時に描画スレッドを作成し、ボタンを押すとロードが開始され、ロードが終わると再生/描画が開始されるというものです。 DrawLoopではLoadGraphを、SoundLoopではLoadSoundMem関数を利用しています。 サンプルプログラムで利用している音源に関しては、下記のサイトのものを利用させていただきました。 ttp://www.sousound.com/music_sample.html ◆Form1.vb Public Class Form1 Private Drawer As DrawClass Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Drawer = New DrawClass End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click Drawer.StartLoad = True End Sub End Class ◆DrawClass.vb Imports DxLibDLL Public Class DrawClass 'スレッド本体の制御関連 Private DrawThread As Threading.Thread Public StartLoad As Boolean 'DxLibのオプション設定と初期化 Private Sub InitDxLib() Dim screen As Screen = Screen.AllScreens(0) '描画先ディスプレイを取得 '解像度と色深度設定 DX.SetGraphMode(screen.Bounds.Width, screen.Bounds.Height, 32) '描画ウィンドウの位置を設定 DX.SetWindowInitPosition(screen.Bounds.X, screen.Bounds.Y) 'ウィンドウモード(枠無し)で起動 DX.ChangeWindowMode(DX.TRUE) DX.SetWindowStyleMode(2) 'ウィンドウがアクティブじゃない時も処理を続ける DX.SetAlwaysRunFlag(DX.TRUE) 'DxLib_Init()を呼んだwindow以外からも操作を可能にする DX.SetMultiThreadFlag(DX.TRUE) '透過チャンネルを有効に設定 DX.SetMovieColorA8R8G8B8Flag(DX.TRUE) '一度裏画面に描画を行い、Flipすると描画が行われるように設定(ダブルバッファリング) DX.SetDrawScreen(DX.DX_SCREEN_BACK) '2枚以上の画面にScreen.flipする場合デフォルトではVSync待ちで遅くなるのでVSyncは切る DX.SetWaitVSyncFlag(DX.FALSE) '多分これが無いとプログラム本体のIME関連動作がおかしくなる DX.SetUseIMEFlag(DX.TRUE) '開発したPCの環境ではこれを使わないとAccessViolationで落ちる、別のPCでは逆にこれを有効にしているとMP4が再生できない? DX.SetUseMediaFoundationFlag(DX.FALSE) If DX.DxLib_Init() = -1 Then '起動できなかった場合はアプリケーションを終了する MsgBox("初期化に失敗しました。", MsgBoxStyle.Critical) End End If End Sub '再生ループ Private Sub DrawLoop() Dim handle As Integer Dim alpha As Byte = 255 While True If StartLoad Then DX.SetUseASyncLoadFlag(DX.TRUE) handle = DX.LoadGraph("Test2.BMP", DX.TRUE) DX.SetUseASyncLoadFlag(DX.FALSE) StartLoad = False ElseIf DX.CheckHandleASyncLoad(handle) <> DX.FALSE Then DX.ProcessMessage() Else DX.ClearDrawScreen() '描画先初期化 '透過値をセットして描画 DX.SetDrawBlendMode(DX.DX_BLENDMODE_ALPHA, alpha) DX.DrawExtendGraph(0, 0, 1000, 1000, handle, DX.TRUE) DX.ScreenFlip() End If End While End Sub '音楽版 Private Sub SoundLoop() Dim handle As Integer Dim alpha As Byte = 255 Dim playStarted = False While True If StartLoad Then DX.SetUseASyncLoadFlag(DX.TRUE) handle = DX.LoadSoundMem("mondo_01.mp3") DX.SetUseASyncLoadFlag(DX.FALSE) StartLoad = False ElseIf DX.CheckHandleASyncLoad(handle) <> DX.FALSE Then DX.ProcessMessage() Else If Not playStarted Then DX.PlaySoundMem(handle, DX.DX_PLAYTYPE_BACK) playStarted = True End If End If End While End Sub '初期化 Public Sub New() InitDxLib() StartLoad = False DrawThread = New Threading.Thread(AddressOf DrawLoop) With { .IsBackground = True } DrawThread.Start() End Sub End Class
メンテ
Re: 非同期ロードが終わらない ( No.12 )
名前:keen 日時:2018/02/18 22:42

こちらでも調査を続けましたが、現在公開されている3.14a以降の全バージョンにおいてこのやり方での画像ロードは不可能のようでした……。
メンテ
Re: 非同期ロードが終わらない ( No.13 )
名前:管理人 日時:2018/02/18 23:44

> 774さん ご返答ありがとうございます 問題があったわけではなかったようで安心しました > keenさん > 自分の作っているプログラムではメインのフォームと描画用スレッドを持ち、そこでDxLib関連の処理を行うという構造になっているので、問題はそこに有るのかもしれません。 おそらく『メインのフォーム』とは別の『描画用スレッド』でDXライブラリの関数を使用していることが原因です DXライブラリでは DxLib_Init を呼ぶスレッドとDXライブラリの関数を呼ぶスレッドが異なる場合の動作の保証はしていません ( DXライブラリは複数のスレッドから関数を呼んでも問題なく動作する『スレッドセーフ』タイプのライブラリではありません ) 非同期読み込み機能も DxLib_Init が呼ばれたスレッドとは別のスレッドで行われることは想定していないので、 非同期読み込みが正常に動作しなかったとしても対応の範囲外となります 申し訳ありませんがプログラムの構造を変更して対応してください m(_ _;m ( 一応、描画スレッドで DxLib_Init を呼べば正常に読み込みが完了することは確認できました )
メンテ
Re: 非同期ロードが終わらない ( No.14 )
名前:keen(解決) 日時:2018/02/19 00:38

解決しました! スレッドの外側でなく、以下のようにスレッドの開始時に呼ぶことで非同期読み込みが正常に完了することを確認できました! ライブラリの基本構造を理解しておらず、お手数おかけいたしました。 '再生ループ Private Sub DrawLoop() InitDxLib() Dim handle As Integer Dim alpha As Byte = 255 While True If StartLoad Then DX.SetUseASyncLoadFlag(DX.TRUE) handle = DX.LoadGraph("Test2.BMP", DX.TRUE) DX.SetUseASyncLoadFlag(DX.FALSE) StartLoad = False ElseIf DX.CheckHandleASyncLoad(handle) <> DX.FALSE Then DX.ProcessMessage() Else DX.ClearDrawScreen() '描画先初期化 '透過値をセットして描画 DX.SetDrawBlendMode(DX.DX_BLENDMODE_ALPHA, alpha) DX.DrawExtendGraph(0, 0, 1000, 1000, handle, DX.TRUE) DX.ScreenFlip() End If End While End Sub
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存