ページ 11

[c#]dxライブラリとwebbrowser

Posted: 2014年7月20日(日) 09:35
by ウインドウマン
現在C#フォームアプリケーションでdxライブラリを使ったゲームを作成しています。
フォームにはピクチャーボックスとwebbrowserが張り付けてあります。
ピクチャボックス内でdxライブラリを使ったゲームを表示させます。
ここで質問があります。
webbrowserを使ってサイトを表示させようとしたときにゲーム画面がカクカクする現象が起きてしまいます。
これをどのようにしたら解決できるでしょうか。

最悪縁なしのフォームを一つ作ってそれをwebbrawserがあったスペースに重ねる方法があるのですが効率が悪いと思います。
下記のようなプログラムを
http://qiita.com/hart_edsf/items/0301f17e2d9acd890c5e
を参考にして書きました。ブラウザは貼り付けてオプションで設定しました。

コード:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DxLibDLL;

namespace WindowsFormsApplication2
{
    public partial class Form1 : Form
    {
        int i = 0;
        public Form1()
        {
            InitializeComponent();
            DX.SetUserWindow(this.Handle);
            DX.SetUserChildWindow(pictureBox1.Handle);
            DX.DxLib_Init();
            DX.SetDrawScreen(DX.DX_SCREEN_BACK);
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            DX.DxLib_End();
        }
        public void MainLoop()
        {
            // 画面に描かれているものを一回全部消す
            DX.ClsDrawScreen();
            DX.DrawString(0, i, "Hello C# World!", -1);
            i++;
            if (i > 200) i = 0;
            // 裏画面の内容を面画面に反映される
            DX.ScreenFlip();
        }

    }
}


Re: [c#]dxライブラリとwebbrowser

Posted: 2014年7月21日(月) 08:12
by ウインドウマン
少し考えてマルチスレッドでフォームを作ることにしました。
しかしform1のFormObj.Show()で
型 'System.InvalidOperationException' のハンドルされていない例外が System.Windows.Forms.dll で発生しました
追加情報:有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'Form1' がアクセスされました。
と表示されます。

どうしたら解決できるでしょうか。

下記がプログラムです。form2.csは何も弄っていません。
program.cs

コード:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace MFORM
{
    static class Program
    {
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです。
        /// </summary>
        [STAThread]
        static void Main()
        {
            // Form1 オブジェクトを生成
            Form1 f1 = new Form1();
            // Form2 オブジェクトを生成
            Form2 f2 = new Form2();

            // Form1 オブジェクトを実行するスレッドを生成し、それを実行
            System.Threading.Thread ThreadObj1 = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(RunForm1Thread));
            ThreadObj1.SetApartmentState(System.Threading.ApartmentState.STA);
            ThreadObj1.Start(f1);

            // Form2 オブジェクトを実行するスレッドを生成し、それを実行
            System.Threading.Thread ThreadObj2 = new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(RunForm2Thread));
            ThreadObj2.SetApartmentState(System.Threading.ApartmentState.STA);
            ThreadObj2.Start(f2);
        }

        static void RunForm1Thread(object data)
        {
            // スレッド引数から、実行対象フォームを取得
            Form1 FormObj = (Form1)data;

            // フォームの実行
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            FormObj.Show();
            while (FormObj.Created) //Application.Runしないで自分でループを作る
            {
                FormObj.MainLoop();
                Application.DoEvents(); //←必要
            }
        }

        static void RunForm2Thread(object data)
        {
            // スレッド引数から、実行対象フォームを取得
            Form2 FormObj = (Form2)data;

            // フォームの実行
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            FormObj.Show();
            while (FormObj.Created) //Application.Runしないで自分でループを作る
            {
                FormObj.MainLoop();
                Application.DoEvents(); //←必要
            }
        }
    }
}
form1.cs

コード:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using DxLibDLL;

namespace MFORM
{
    public partial class Form1 : Form
    {
        int i;
        public Form1()
        {
            InitializeComponent();
            DX.SetUserWindow(this.Handle);
            DX.SetUserChildWindow(pictureBox1.Handle);
            DX.SetOutApplicationLogValidFlag(DX.FALSE);
            DX.DxLib_Init();
            DX.SetDrawScreen(DX.DX_SCREEN_BACK);
        }

        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            DX.DxLib_End();
        }

        public void MainLoop()
        {
            // 画面に描かれているものを一回全部消す
            DX.ClsDrawScreen();
            DX.DrawString(0, 100 + (int)(100 * Math.Sin(i * Math.PI / 180.0)), "Hello C# World!", -1);
            i++;
            if (i > 360) i = 0;
            // 裏画面の内容を面画面に反映される
            DX.ScreenFlip();
        }
    }
}


Re: [c#]dxライブラリとwebbrowser

Posted: 2014年7月21日(月) 17:44
by バグ
少し記事が古いですが、ここが参考になるかと思います。

Re: [c#]dxライブラリとwebbrowser

Posted: 2014年7月21日(月) 23:12
by ウインドウマン
回答ありがとうございます。
さっそくサイトを見てみましたが書いたプログラムにどのように適用すればいいのかわかりません。
その辺のところも教えていただきたいのですが。
よろしくおねがいします。

Re: [c#]dxライブラリとwebbrowser

Posted: 2014年7月24日(木) 17:16
by ウインドウマン
program.cs
form1.cs
のどちらにもinvokeを書かなければならないでしょうか。

Re: [c#]dxライブラリとwebbrowser

Posted: 2014年7月25日(金) 22:57
by ウインドウマン
c#でマルチスレッドは難しいのでしょうか。
もっと専門的なサイトに質問するべきですか?

Re: [c#]dxライブラリとwebbrowser

Posted: 2014年7月27日(日) 23:06
by YuO
ウインドウマン さんが書きました:c#でマルチスレッドは難しいのでしょうか。
もっと専門的なサイトに質問するべきですか?
C#でマルチスレッドが難しいかと問われればYESです。
ただし,それはマルチスレッド一般における難しさそのもので,
つまり,アクセスのアトミック性,同期・排他などをちゃんと考えないといけない,という点に関してです。

.NET FrameworkやC#のマルチスレッドプログラミングは,相対的には簡単だと思いますし,簡単になってきています。
ref) http://dixq.net/forum/blog.php?u=546&b=3452

ウインドウマン さんが書きました:program.cs
form1.cs
のどちらにもinvokeを書かなければならないでしょうか。
InvokeはWinFormsのUI ControlがCOMのSTAモデルに基づいており,クロススレッドのアクセスが禁じられているために利用されるものです。
つまり,Formを定義したスレッドでInvokeを使う必要はまったくありません。
使えばよいかが判断できないというのであれば,InvokeRequiredプロパティを毎回確認すればよいでしょう。
オフトピック
WebBrowserコントロールなんていう重量級コンポーネントを使う以上,UIスレッドが(ユーザーに分からない程度に)ブロックされるのは仕方がないかと。
WinRTの設計思想でも50ms以上かかる処理は非同期 = 50ms程度の処理は許容範囲内であり,
ユーザーアクションから100ms程度ウィンドウメッセージが処理されなくても,通常のアプリケーションにおいては問題ないことが多いです。
ある程度のリアルタイム性能が求められる通信などは別スレッドで処理するのが普通でしょうし。

Re: [c#]dxライブラリとwebbrowser

Posted: 2014年7月30日(水) 15:43
by ウインドウマン
回答ありがとうございます。
具体的にはどのようにやればいいでしょうか?

Re: [c#]dxライブラリとwebbrowser

Posted: 2014年8月04日(月) 13:24
by ウインドウマン
webbrowserとDXライブラリを同じフォームに表示させているので一瞬でも止まると残念な形になります。
2つフォームを作り独立させて動かそうと思たのですが連動しているようで片方が止まるともう片方も止まってしまいます。
フォームのマルチスレッドを考えましたがうまくいきませんでした。

Re: [c#]dxライブラリとwebbrowser

Posted: 2014年8月06日(水) 10:20
by ウインドウマン
webbrowser内でjavascriptを使用して自動的にページを更新しようとしているのですが、その時に瞬間的にフォームが止まるのですがこれはどうすれば解決できるでしょうか。