20210123のC#に関する記事は7件です。

WPFでMahAppsとMaterialDesignを使用しているとDark, Lightモードで表示がうまくいかなくなる

はじめに

以前MahAppsでカラー設定の保存と利用という記事を書きましたが、そこでテーマをDarkモードにした場合、文字が白抜きになるのはずなのですが、コントロールによって黒文字のままだったり、白背景に白文字という現象が起きました。

問題

本当はこう(Dark)なのに
image.png
それがこうなる(一番左のListBoxが黒文字)
image.png

Lightの場合本当はこうなるはず
image.png
それがこうなる(罫線が見えない(白い?))
image.png

解決

以前の記事でSetThemeAndColorを呼び出していましたが、その前に以下のようにApplyBaseThemeを呼び出して設定するとうまくいきました。

using MaterialDesignThemes.Wpf;

private readonly PaletteHelper _paletteHelper = new PaletteHelper();

public void ApplyBaseTheme(bool isDark)
{
    ITheme theme = _paletteHelper.GetTheme();
    IBaseTheme baseTheme = isDark ? new MaterialDesignDarkTheme() : (IBaseTheme)new MaterialDesignLightTheme();
    theme.SetBaseTheme(baseTheme);
    _paletteHelper.SetTheme(theme);
}

MaterialDesign側のテーマ設定を先に行って、それから通常のテーマ設定をするとうまくカラーが設定できるようです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

EntityFramewofk Coreで自動採番となっているテーブルで指定のIDを追加したい

はじめに

現在利用しているアプリを新規アプリに変更するにあたってSQL Serverに新しくデータベースを作って、そこに元のデータをいれようと思っていました。
テーブルをコードファーストで作っていたのですが、これだと旧テーブルから新テーブルにデータを移行する際に、IDが変わってしまうという問題がありました。
そこで、いろいろと調べていると、SET IDENTITY_INSERT [table名] ON を行えばいいということが分かり実装してみました。

問題が起きました

Master_Staff(旧テーブル) ⇒ Main_User(新テーブル)
蛇足ですが、昨今の"Master"は使わないようにしようという流れにあわせて、新規アプリでテーブル名を変更することにしました。

    internal async Task InsertMainUserAsync(newDBContext dbContext, List<Master_Staff> MasterStaffs)
    {
        await Task.Run(() =>
        {
            foreach (var s in MasterStaffs)
            {
                dbContext.Main_Users.Add(new Main_User()
                {
                    Main_UserId = s.Master_StaffId,
                    UserName = s.StaffName,
                });
            }
            dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users ON");
            dbContext.SaveChanges();
            dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users OFF");
        }
    }

SqlException: IDENTITY_INSERT が OFF に設定されているときは、テーブル 'Main_Users' の ID 列に明示的な値を挿入できません。
というエラーが起きました。

解決

いろいろと調べると、Microsoft Documentに生成されるプロパティに明示的な値を設定するというページがありました
そこにあるSampleは以下の通り

using (var context = new EmployeeContext())
{
    context.Employees.Add(new Employee { EmployeeId = 100, Name = "John Doe" });
    context.Employees.Add(new Employee { EmployeeId = 101, Name = "Jane Doe" });

    context.Database.OpenConnection();
    try
    {
        context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Employees ON");
        context.SaveChanges();
        context.Database.ExecuteSqlRaw("SET IDENTITY_INSERT dbo.Employees OFF");
    }
    finally
    {
        context.Database.CloseConnection();
    }
}

どうやら、同じ接続内でSET IDENTITY_INSERTを行わないとエラーになるようでした。
ということで以下のようにコードを変更したらうまくいきました。

    internal async Task InsertMainUserAsync(newDBContext dbContext, List<Master_Staff> MasterStaffs)
    {
        await Task.Run(() =>
        {
            foreach (var s in MasterStaffs)
            {
                dbContext.Main_Users.Add(new Main_User()
                {
                    Main_UserId = s.Master_StaffId,
                    UserName = s.StaffName,
                });
            }

            //ExecuteSqlRawとSaveChangesの部分を以下のように変更しました。
            dbContext.Database.OpenConnection();
            try
            {
                dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users ON");
                dbContext.SaveChanges();
                dbContext.Database.ExecuteSqlRaw("SET IDENTITY_INSERT Main_Users OFF");
            }
            finally
            {
                dbContext.Database.CloseConnection();
            }
        }
    }

分かってしまえばなんてことないことですが、分かるまでは「なんで?」と思って、他にいろいろと原因を探して、無駄な時間を費やしてしまいます。
同じように困っている人がいれば、参考となればと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SemaphoreSlimの使い方

同時に仕事をできる机(Task)の数を制限するのがSemaphoreSlimです。
company_syokuba_kengaku_business.png

基本

//机を2つ用意
SemaphoreSlim ss = new SemaphoreSlim(2);

//机が1つ埋まる
ss.Wait();

//机がもう1つ埋まる
ss.Wait();

//机を1つだけ空ける
ss.Release(1);

//空いてる机の数を確認
Console.WriteLine(ss.CurrentCount);
//実行結果は、1

簡単な例

using System;
using System.Threading;
using System.Threading.Tasks;

class Program {
    static void Main(string[] args) {

        SemaphoreSlim ss = new SemaphoreSlim(0);    //最初は、机を1つも作らない
        ss.Release(1);      //机を1つだけ追加

        //机が1つしかないので、作業1だけが実行される
        Task task1 = Task.Run(() =>{ss.Wait();  Console.WriteLine("作業1");});
        Task task2 = Task.Run(() =>{ss.Wait();  Console.WriteLine("作業2");});

        //1つしかない机は、作業1で埋まっているので、0
        Console.WriteLine(  ss.CurrentCount);

        Console.ReadLine();
    }
}

引数

SemaphoreSlim ss = new SemaphoreSlim(1, 6); 

第1引数は、机の数(後から追加できる)
第2引数は、机の最大数
机は1つしかないが、最大6つまで増やせられる。

Waitと、WaitAsyncの違い

using System;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
class Program {
    static void Main(string[] args) {
        Sub();
        Console.WriteLine("main");      //A
        Console.ReadLine();
    }
    public static async Task Sub() {
        SemaphoreSlim ss = new SemaphoreSlim(2);
        List<Task> list = new List<Task>();
        int num = 10;

        while(num-- > 0) {
            await ss.WaitAsync();       //B     Aが先に実行される(非同期)
            //ss.Wait();                //C     Aが後に実行される(同期)

            list.Add(   Task.Run(   () => {
                Thread.Sleep(100);
                Console.WriteLine("-");
                ss.Release();
            }));
        }
        await Task.WhenAll(list);
    }
}

Waitは、呼び出し元を待機させ(同期)
WaitAsyncは、待機させません(非同期)

Waitメソッドは入れたらTrueを返します。
既に満席で入れなかったらFalseを返します。

キャンセル

CancellationToken はまず CancellationTokenSource を生成した上で、
CancellationTokenSource.Token より取得します。

キャンセルを要求するには CancellationTokenSource.Cancel() を呼びます。

つづく・・・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SemaphoreSlimのかんたんな使い方

同時に仕事をできる机(Task)の数を制限するのがSemaphoreSlimです。
company_syokuba_kengaku_business.png

基本

//机を2つ用意
SemaphoreSlim ss = new SemaphoreSlim(2);

//机が1つ埋まる
ss.Wait();

//机がもう1つ埋まる
ss.Wait();

//机を1つだけ空ける
ss.Release(1);

//空いてる机の数を確認
Console.WriteLine(ss.CurrentCount);
//実行結果は、1

簡単な例

using System;
using System.Threading;
using System.Threading.Tasks;

class Program {
    static void Main(string[] args) {

        SemaphoreSlim ss = new SemaphoreSlim(0);    //最初は、机を1つも作らない
        ss.Release(1);      //机を1つだけ追加

        //机が1つしかないので、作業1だけが実行される
        Task task1 = Task.Run(() =>{ss.Wait();  Console.WriteLine("作業1");});
        Task task2 = Task.Run(() =>{ss.Wait();  Console.WriteLine("作業2");});

        //1つしかない机は、作業1で埋まっているので、0
        Console.WriteLine(  ss.CurrentCount);

        Console.ReadLine();
    }
}

引数

SemaphoreSlim ss = new SemaphoreSlim(1, 6); 

第1引数は、机の数(後から追加できる)
第2引数は、机の最大数
机は1つしかないが、最大6つまで増やせられる。

Waitと、WaitAsyncの違い

using System;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
class Program {
    static void Main(string[] args) {
        Sub();
        Console.WriteLine("main");      //A
        Console.ReadLine();
    }
    public static async Task Sub() {
        SemaphoreSlim ss = new SemaphoreSlim(2);
        List<Task> list = new List<Task>();
        int num = 10;

        while(num-- > 0) {
            await ss.WaitAsync();       //B     Aが先に実行される(非同期)
            //ss.Wait();                //C     Aが後に実行される(同期)

            list.Add(   Task.Run(   () => {
                Thread.Sleep(100);
                Console.WriteLine("-");
                ss.Release();
            }));
        }
        await Task.WhenAll(list);
    }
}

Waitは、呼び出し元を待機させ(同期)
WaitAsyncは、待機させません(非同期)

Waitメソッドは入れたらTrueを返します。
既に満席で入れなかったらFalseを返します。

キャンセル

CancellationToken はまず CancellationTokenSource を生成した上で、
CancellationTokenSource.Token より取得します。

キャンセルを要求するには CancellationTokenSource.Cancel() を呼びます。

つづく・・・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

かんたんな「SemaphoreSlim」の使い方

同時に仕事をできる机(Task)の数を決めるのが、SemaphoreSlimです。
company_syokuba_kengak:relaxed:u_business.png

基本

//机を2つ用意
SemaphoreSlim ss = new SemaphoreSlim(2);

//机が1つ埋まる
ss.Wait();

//机がさらに1つ埋まる
ss.Wait();

//2つとも埋まった机のうち、1つだけ空ける
ss.Release(1);

//空いてる机の数を確認
Console.WriteLine(ss.CurrentCount);
//実行結果は、1

Waitで机を使う。
Releaseで机を空けるか、新しい机を用意する。
CurrentCountで机の数を確認

かんたんな例

using System;
using System.Threading;
using System.Threading.Tasks;

class Program {
    static void Main(string[] args) {

        SemaphoreSlim ss = new SemaphoreSlim(0);    //最初は、机を1つも作らない
        ss.Release(1);      //机を1つだけ追加

        //机が1つしかないので、作業1だけが実行される
        Task task1 = Task.Run(() =>{ss.Wait();  Console.WriteLine("作業1");});
        Task task2 = Task.Run(() =>{ss.Wait();  Console.WriteLine("作業2");});

        //1つしかない机は、作業1で埋まっているので、0
        Console.WriteLine(  ss.CurrentCount);

        Console.ReadLine();
    }
}

Taskを実行しようとしても、空いてる机の数しか実行されない

引数

SemaphoreSlim ss = new SemaphoreSlim(1, 6); 

第1引数は、机の数(あとから追加できる)
第2引数は、机の最大数
机は1つしかないが、最大6つまで増やせられる。

SemaphoreSlim ss = new SemaphoreSlim(1); 

引数は机の数(最大数は未設定なので、あとからいくらでも追加できる)

Waitと、WaitAsyncの違い

using System;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;

class Program {
    static void Main(string[] args) {
        Sub();
        Console.WriteLine("main");      //A
        Console.ReadLine();
    }
    public static async Task Sub() {
        SemaphoreSlim ss = new SemaphoreSlim(2);
        List<Task> list = new List<Task>();
        int num = 10;

        while(num-- > 0) {
            await ss.WaitAsync();       //B     Aが先に実行される(非同期)
            //ss.Wait();                //C     Aが後に実行される(同期)

            list.Add(   Task.Run(   () => {
                Thread.Sleep(100);
                Console.WriteLine("-");
                ss.Release();
            }));
        }
        await Task.WhenAll(list);
    }
}

Waitは、呼び出し元を待機させ(同期)
WaitAsyncは、待機させません(非同期)

Waitメソッドは入れたらTrueを返します。
既に満席で入れなかったらFalseを返します。

キャンセル

CancellationToken はまず CancellationTokenSource を生成した上で、
CancellationTokenSource.Token より取得します。

キャンセルを要求するには CancellationTokenSource.Cancel() を呼びます。

つづく・・・

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Unity:Addressable でコンテンツをダウンロード

Addresablesでコンテンツをサーバからダウンロードする方法

環境

OS macOS 10.15.7
Unity 2019.4.2f1
Addressable 1.16.15


PackageManagerからAdressablesをインストール

スクリーンショット 2021-01-21 13.52.57.png

WindowメニューからAsset Management->Addressables->Groupsを選択
スクリーンショット 2021-01-21 13.54.11.png

Create Addressables Settingsをクリック
スクリーンショット 2021-01-21 13.54.26.png

オブジェクトを配置する。オブジェクトは一度ProjectにドラッグしPrefabにする。この例では「Object」と名前をつけた。
PrefabにしたオブジェクトはHierarchyから削除する。
PrefabはAddressableにチェックを入れる。
スクリーンショット 2021-01-21 13.59.33.png

カラのGameObjectを生成し、その中に下記のスクリプトを記述する。ここではファイル名を「LoadScript」とした。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

using UnityEngine.AddressableAssets; 
using UnityEngine.ResourceManagement.AsyncOperations;

public class LoadScript : MonoBehaviour

{
    public AssetReference reference;

    // Start is called before the first frame update
    void Start()
    {
        reference.InstantiateAsync();
    }

}

上記のスクリプトのInspecterには下図のようなUIが表示されるので、リモートからロードするPrefabを選択する。
スクリーンショット 2021-01-21 14.04.39.png
上記のUIがInspectorに表示されない場合は、Project WindowでRefleshする。
スクリーンショット 2021-01-21 14.04.21.png

AdressableAssetSettingのInspectorでCatalogの設定をおこなう。
Assets>AddresableAssetsDataの中にあるAdressableAssetSettingをクリックしてInspectorを表示する。
スクリーンショット 2021-01-21 14.27.20.png

「Build Remote Catalog」にチェックを入れる。
「Build Remote Caralog」はRemoteBuildPathを選択。
「LoadPath」はRemoteLodePathを選択。
ここではlocalhostのStandaloneOSXフォルダを参照するようになっている。
スクリーンショット 2021-01-21 14.27.08.png

LoadPathのURLを変更する際にはWindow>Addressable Management>Addresbles>Profilesを開きRemoteLoadPathのURLを変更する。
スクリーンショット 2021-01-22 22.20.10.png
スクリーンショット 2021-01-22 22.16.29.png

リモートサーバにアップするファイルのビルドを行う。
Play Mode ScriptのUse Existing Buildを選択
スクリーンショット 2021-01-21 14.07.52.png
Build>New Build> Default Build Scriptを選択肢ビルドする。
スクリーンショット 2021-01-22 22.24.38.png

プロジェクトのフォルダ内にSarverDataフォルダが出来ているはず。
その中にBuildTarget名のフォルダをアプリが参照するディレクトリにコピーする。
スクリーンショット 2021-01-22 22.28.26.png
macOSの場合httpServerが/Library/WebServer/Documentsを参照するので下記の様になる
スクリーンショット 2021-01-22 22.35.34.png

最後にアプリをBuild and Runを実行する。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

岩永さんの配信の「Visual Studio 16.9 Preview 3 リリース (C# 10.0 追加予定機能ちょっとあり)」に参加してきました

Visual Studio 16.9 Preview 3 リリース (C# 10.0 追加予定機能ちょっとあり)
image.png

今回も岩永さんの動画にお邪魔させてもらいました。

岩永さんの配信は 1 つの配信に対して 1 Issue という感じになっています。なので、Issue を見るとポイントになった箇所のコードとかが簡単な説明と共に書いてあるので、Issue を見るだけでも内容がわかって忙しい人にはお勧めです!(一番はライブで見るですけど!)

https://github.com/ufcpp-live/UfcppLiveAgenda/issues/24

今回のおすすめポイント

自分的には最後にあった XALM で DataContext プロパティに設定する ViewModel を生成してくれるところと、PInvoke のコードを生成している CsWin32 です。

該当コメントへの直リンク

P/Invoke 話が盛り上がった。

XAML からの ViewModel 生成。INotifyPropertyChanged も生成してる。プロパティ生成もあった。

まとめ

ということで、今後も配信に参加したらこんな感じで軽いまとめを書いてみようと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む