C#,VB.NET,ソフトウェア開発

返り値のないメソッドの場合

        private async void btnStart_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff"));

            await Count();

            Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff"));
        }

        private async Task Count()
        {
            int intValue = 1;

            await Task.Run(() =>
            {
                for(int intCount = 0; intCount < 15; intCount++)
                {
                    intValue *= 2;
                    Console.WriteLine(intValue);

                    System.Threading.Thread.Sleep(100);
                }
            });
        }

 

別スレッドからキャンセル処理を行う場合は下記のようになる。

        // トークン
        private CancellationTokenSource objToken = null;

        private async void btnStart_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff"));

            await Count();

            Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff"));
        }

        private async Task Count()
        {
            int intValue = 1;

            objToken = new CancellationTokenSource();

            await Task.Run(() =>
            {
                for(int intCount = 0; intCount < 15; intCount++)
                {
                    // キャンセルフラグが立っていたら処理を抜ける
                    if(objToken.IsCancellationRequested == true)
                    {
                        return;
                    }

                    intValue *= 2;
                    Console.WriteLine(intValue);

                    System.Threading.Thread.Sleep(100);
                }
            }, objToken.Token);
        }

        /// <summary>
        /// キャンセル処理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            if(objToken != null)
            {
                objToken.Cancel();
            }
        }

また、IsCancellationRequested ではなく ThrowIfCancellationRequested を用いることで、
例外として処理することもできる。

        // トークン
        private CancellationTokenSource objToken = null;

        private async void btnStart_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff"));

            try
            {
                await Count();
                Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff"));
            }
            catch (OperationCanceledException exCanceled)
            {
                // キャンセル時
                Console.WriteLine("Canceled:" + DateTime.Now.ToString("HH:mm:ss.ff"));
            }
        }

        private async Task Count()
        {
            try
            {
                int intValue = 1;

                objToken = new CancellationTokenSource();

                await Task.Run(() =>
                {
                    try
                    {
                        for (int intCount = 0; intCount < 15; intCount++)
                        {
                            // キャンセルフラグが立っていたらOperationCanceledExceptionを発生させる
                            objToken.Token.ThrowIfCancellationRequested();

                            intValue *= 2;
                            Console.WriteLine(intValue);

                            System.Threading.Thread.Sleep(100);
                        }
                    }
                    catch (OperationCanceledException exCanceled)
                    {
                        // キャンセル時
                        throw (exCanceled);
                    }
                }, objToken.Token);
            }
            catch (Exception ex)
            {
                throw (ex);
            }
        }

        /// <summary>
        /// キャンセル処理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            if (objToken != null)
            {
                objToken.Cancel();
            }
        }

 

 

返り値のあるメソッドの場合

        private async void btnStart_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff"));

            int intResult = await Count();

            Console.WriteLine("Total:" + intResult);

            Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff"));
        }

        private async Task<int> Count()
        {
            int intValue = 1;
            
            int intResult = await Task.Run(() =>
            {
                int intSum = 0;

                for(int intCount = 0; intCount < 15; intCount++)
                {
                    intValue *= 2;
                    Console.WriteLine(intValue);

                    intSum += intValue;

                    System.Threading.Thread.Sleep(100);
                }

                return intSum;
            });

            return intResult;
        }

 

また、VB.NETの場合は下記のようになる(返り値のないメソッド)

    Private Async Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
        Debug.Print("Start:" + DateTime.Now.ToString("HH:mm:ss.ff"))

        Await Count()

        Debug.Print("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff"))
    End Sub

    Private Async Function Count() As Task
        Dim intValue As Integer = 1

        Await Task.Run(Sub()
                           For intCount = 0 To 14
                               intValue *= 2
                               Debug.Print(intValue)

                               System.Threading.Thread.Sleep(100)
                           Next
                       End Sub)
    End Function

 

C#,ソフトウェア開発

        // サンプルデータ
        private List<string> lstData = new List<string> { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K" };

        /// <summary>
        /// 通常処理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStart_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff"));
            Console.WriteLine("For文");
            for (int intCount = 0; intCount < lstData.Count; intCount++)
            {
                Console.WriteLine(lstData[intCount]);
                System.Threading.Thread.Sleep(300);
            }

            Console.WriteLine("ForEach文");
            foreach (string strData in lstData)
            {
                Console.WriteLine(strData);
                System.Threading.Thread.Sleep(300);
            }
            Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff"));
        }
Start:12:00:32.75
For文
A
B
C
D
E
F
G
H
I
J
K
ForEach文
A
B
C
D
E
F
G
H
I
J
K
Finish:12:00:39.36

 

これにParallelを適用すると、下記のようになる。

        // サンプルデータ
        private List<string> lstData = new List<string> { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K" };

        /// <summary>
        /// パラレル処理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnParallelStart_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff"));
            Console.WriteLine("Parallel.For文");
            Parallel.For(0, lstData.Count, intCount =>
            {
                Console.WriteLine(lstData[intCount]);
                System.Threading.Thread.Sleep(300);
            });

            Console.WriteLine("Parallel.ForEach文");
            Parallel.ForEach(lstData, strData =>
            {
                Console.WriteLine(strData);
                System.Threading.Thread.Sleep(300);
            });
            Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff"));
        }
Start:12:01:43.02
Parallel.For文
A
C
D
E
F
G
H
I
J
B
K
Parallel.ForEach文
A
E
D
F
B
G
H
C
I
J
K
Finish:12:01:44.24

並列に処理を行うため、全体の処理速度が向上している反面、処理の順番がバラバラになっていることに注意されたい。

 

並列処理内部でBreakを行いたい場合は下記のようになる。

        /// <summary>
        /// パラレル処理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnParallelStart_Click(object sender, EventArgs e)
        {
            Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff"));
            Console.WriteLine("Parallel.For文");
            Parallel.For(0, lstData.Count, (intCount, objLoopState) =>
            {
                Console.WriteLine(lstData[intCount]);

                if (lstData[intCount] == "G")
                {
                    objLoopState.Break();
                }

                System.Threading.Thread.Sleep(300);
            });

            Console.WriteLine("Parallel.ForEach文");
            Parallel.ForEach(lstData, (strData, objLoopState) =>
            {
                Console.WriteLine(strData);

                if (strData == "G")
                {
                    objLoopState.Break();
                }

                System.Threading.Thread.Sleep(300);
            });
            Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff"));
        }
Start:12:07:37.11
Parallel.For文
A
C
B
D
E
F
G
Parallel.ForEach文
A
F
D
E
G
B
C
Finish:12:07:37.73

Gが処理されたタイミングでBreakをかけているが、すでに並列処理が走ってしまっている分に関しては処理されてしまうので注意。

 

また、外部のスレッドから処理を中断する場合は下記のようになる。

        // トークン
        private CancellationTokenSource objToken = null;

        /// <summary>
        /// パラレル処理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private async void btnParallelStart_Click(object sender, EventArgs e)
        {
            try
            {
                await Task.Run(() =>
                {
                    // ParallelOptionsの構築
                    objToken = new CancellationTokenSource();
                    ParallelOptions options = new ParallelOptions();
                    options.CancellationToken = objToken.Token;

                    Console.WriteLine("Start:" + DateTime.Now.ToString("HH:mm:ss.ff"));
                    Console.WriteLine("Parallel.For文");
                    Parallel.For(0, lstData.Count, options, intCount =>
                    {
                        Console.WriteLine(lstData[intCount]);
                        System.Threading.Thread.Sleep(300);
                    });

                    Console.WriteLine("Parallel.ForEach文");
                    Parallel.ForEach(lstData, options, strData =>
                    {
                        Console.WriteLine(strData);
                        System.Threading.Thread.Sleep(300);
                    });
                    Console.WriteLine("Finish:" + DateTime.Now.ToString("HH:mm:ss.ff"));
                });
            }
            catch (OperationCanceledException ex)
            {
                // キャンセルされた際に入る例外処理
                Console.WriteLine("Cancel:" + DateTime.Now.ToString("HH:mm:ss.ff"));
            }
        }

        /// <summary>
        /// パラレル処理のキャンセル
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnParallelBreak_Click(object sender, EventArgs e)
        {
            if (objToken != null)
            {
                objToken.Cancel();
            }
        }

 

C#,ソフトウェア開発

System.Windows.Forms.WebBrowserは、デフォルト状態ではIE7相当。

確認サイト:User Agent String.Com

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;

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

        private void Form1_Shown(object sender, EventArgs e)
        {
            webBrowser1.Navigate("http://www.useragentstring.com/");
        }
    }
}

 

IE11に変更する場合は、レジストリ「HKEY_CURRENT_USERSOFTWAREMicrosoftInternet ExplorerMainFeatureControlFEATURE_BROWSER_EMULATION」に

プロセス名と対応するデータを登録する。

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;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private const string strRegPath = @"SoftwareMicrosoftInternet ExplorerMainFeatureControlFEATURE_BROWSER_EMULATION";
        private Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(strRegPath, true);
        private string strProcessName = System.Diagnostics.Process.GetCurrentProcess().ProcessName + ".exe";

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            regKey.SetValue(strProcessName, 11001, Microsoft.Win32.RegistryValueKind.DWord);

            webBrowser1.Navigate("http://www.useragentstring.com/");
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            regKey.DeleteValue(strProcessName);
            regKey.Close();
        }
    }
}

 

レジストリに登録するデータを変更すると、他のレンダリングバージョンに変更することも可能。

MSDN Internet Feature Controls (B..C) (Internet Explorer)

 

また、レジストリを使用せず、NavigateメソッドのadditionalHeadersに、直接UserAgentを指定する方法もある。

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;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private const string strUserAgent = @"User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Shown(object sender, EventArgs e)
        {
            webBrowser1.Navigate("http://www.useragentstring.com/", "_self", null, strUserAgent);
        }
    }
}

C#,WPF,ソフトウェア開発,メモ

マテリアルデザインのウィンドウにしてくれるライブラリ

Material Design In XAML Toolkit

 

ウィンドウの枠を光らせてくれるライブラリ
MetroRadiance

C#,ソフトウェア開発

System.Threading.Thread.Sleep() を用いてSleep処理を行うと、アプリケーションがフリーズしてしまう。

別スレッドを作成し、Joinで終了を待つことで回避することもできるが、制約が多い。

        // using System.Threading;

        protected override void main()
        {
            Thread objThread = new Thread(new ParameterizedThreadStart(ThredSleep));
            objThread.Start(5000);
            objThread.Join();

            MessageBox.Show("OK");
        }

        /// <summary>
        /// 待機処理
        /// </summary>
        /// <param name="millisecondsTimeout">
        /// スリープするミリ秒
        ///  ParameterizedThreadStartの制約上、object型である必要がある。
        /// </param>
        private void ThredSleep(object millisecondsTimeout)
        {
            Thread.Sleep((int)millisecondsTimeout);

async/awaitを用いてSleep処理を行うこと下記のようになる。

        protected override async void main()
        {
            await AsyncSleep(5000);

            MessageBox.Show("OK");
        }

        /// <summary>
        /// 待機処理
        /// </summary>
        /// <param name="millisecondsTimeout">スリープするミリ秒</param>
        private async Task AsyncSleep(int millisecondsTimeout)
        {
            await Task.Delay(millisecondsTimeout);
        }

 

C#,WPF,ソフトウェア開発

App.xamlのStartupUriを消去し、自動起動される画面を除去

・修正前

<Application x:Class="WpfApplication.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

・修正後

<Application x:Class="WpfApplication.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:WpfApplication">
    <Application.Resources>
         
    </Application.Resources>
</Application>

 

App.xaml.csにOnStartupをオーバーライドし、各画面オブジェクトを生成、Showする。

    public partial class App : Application
    {

        static MainWindow objMainWindow;
        static MainWindow objMainWindow2;

        protected override void OnStartup(StartupEventArgs e)
        {
            objMainWindow = new MainWindow();
            objMainWindow2 = new MainWindow();

            objMainWindow.Show();
            objMainWindow2.Show();
        }

    }

 

全ての画面が閉じられると、プロセスが終了する。