主にDIYのブログ

主にDIYのブログ

ブログの説明を入力しません。

安い雨水タンクを見つけ、買うことにしたので、雨どいからの集水器(こういうの)をペットボトル2個+色々で自作。

要件は、

 

・雨どい内側面を伝って落ちてくる雨水を残さずゲット

・タンク満水後は下の雨どいへ流す

 

なので、↓こんな感じか。1.5Lペットボトル上部2個を重ね逆さにする。上段側には水槽ポンプ等についてた余りものパイプをバスボンド等で接着&側面にオーバーフロー穴。下段側にはパイプを通す穴を空けパイプ通し接着。あとはタンクの満水位置に合わせて雨どいをカットしこれを挟むだけ。

 

 

あと、永く使いたいならタンクは日影に置くべし。

 

それにしても、店はなぜタンク扱うのに集水器扱わん…。

うちの庭池の循環システム。池部分はFRP工房福井の1-Bと12を組み合わせたもので、水量約1t。ポンプはRio+ 1400。濾過は落ち葉受けだけで、濾したり吸着させたり等消耗品使う様な処理はしてない。それでも日向にあるのに夏でも完全に透明。

秘密はUVバズーカ。一日2~3時間の点灯でこうなるんだからマジ凄い。

 

 

あと特筆すべきはオーバーフロー排水口。下図左の様に何もしないと浮いてるものをじゃんじゃん吸い込む。メッシュ等被せても、葉の数枚ですぐ詰まる。そこで下図右の様に、底部に空気穴開けたペットボトル下半分を逆さにして被せる。ゴミは大抵浮くか沈むかなので、中層から吸い込む様にすれば詰まりは激減する。

あと底には何も敷いてなかったが落ち葉等が積もっていってる。ヘドロ化が心配だったが、ドジョウとカメが随時かき回してるので大丈夫そう。そのまま「土」ってことで。

 

今の悩みは糸状藻。ミナミヌマエビじゃ効果ないので、日影増、富栄養化抑制が必要?

底部沈殿物と水を畑に移動し水少しずつ入れ替えたり、浮いた落ち葉の除去(網よりトングが便利)かな?

c#.netでのマルチスレッド云々の話。

ボタンのハンドラ内で、

Task task = Task.Delay(4000);
task.ContinueWith((t)=>{ textBox3.Text = "hoge"; }, TaskContinuationOptions.ExecuteSynchronously);

↑これだとスレッド跨いだUI操作で例外発生。(ただしDebugビルド時のみ。Releaseビルド時には出ない!
Task.Delay()は別スレッドを返し、そのスレッドでContinueWith()するから?

 

task.ContinueWith((t) => { textBox3.Text = "hoge"; }, TaskScheduler.FromCurrentSynchronizationContext());

↑これなら通る。

強制的にUIスレッドでContinueWith()させてるから?

 

あるいは、

private async Task aaa()
{
    await Task.Delay(4000);
}

 

private void button3_Click(object sender, EventArgs e)
{
    Task task = aaa();
    task.ContinueWith((t)=>{ textBox3.Text = "hoge"; }, TaskContinuationOptions.ExecuteSynchronously);
}

↑これも通る。

Task.Delay()が返す別スレッドはawaitで消化され、aaa()もContinueWith()もUIスレッドで実行されるから?

だから

await Task.Delay(4000).ConfigureAwait(false);

↑こうすると通らない。

await以降も別スレッド継続させ、その別スレッドでContinueWith()を実行させてるから?

だから

task.ContinueWith((t) => { textBox3.Text = "hoge"; }, TaskScheduler.FromCurrentSynchronizationContext());

↑こうすれば通る。

強制的にUIスレッドでContinueWith()させてるから?

 

なので、遡って、Task.Run()でaaa()自体を別スレッドにした場合、

private async Task aaa()
{
    await Task.Delay(4000);
}

private void button3_Click(object sender, EventArgs e)
{
    Task task = Task.Run(() => aaa());
    //Task task = Task.Run(async () => await aaa());    //こっちでもほぼ同じ

    task.ContinueWith((t)=>{ textBox3.Text = "hoge"; },
        TaskContinuationOptions.ExecuteSynchronously    //これは通らず
        TaskScheduler.FromCurrentSynchronizationContext()    //これは通る
    );
}

こんな感じか。

スレッド遷移周りの理解が甘いなー。ヨクワカラン。

新築の注文住宅の、自分で設計したオリジナル全館空調の仕組み。自分で言うのもなんだが、業者も読むべき高レベルの記事。

 

●特徴

普通の家庭用エアコンを軸に、ほぼ全て汎用の機器・部品で構成。そしてほぼ全て通販で買い、設置のみ工務店に頼んだので、かなり激安。(融通利く工務店で良かった…)

しかも、一般の全館空調システム(エアコン室設置方式、全ダクト方式)と比べて、エアコン室不要メンテナンス厄介なダクト少な目換気扇の風量切り替えで各部屋毎の温度調整可能猫トイレ排気付きとかなり満足できる出来栄え。

 

●詳細

まず建築確認は普通の第三種換気で通す。ただし、トイレの排気ファンは人感センサーシャッター付き換気扇(FY-08PFR9D)にして、居住後は自然給気口は閉じたまま、トイレファンは使用時のみ回るようにする。

 

1階は廊下に熱交換換気扇(FY-12VBD2SCLVB-KB105M)、LDKに普通の壁掛けエアコンを設置。廊下から熱交換排気、猫トイレからバイパス排気しつつ、熱交換給気をエアコン吸気口上に行う。

洗面所と和室については、隣室だし特に和室はたまにしか使わないので、大仰なダクトなんて不要。壁設置の室間換気扇(V-08PFE)で必要なときのみ空気を送る。

 

2階も概ね同じ方針だが、こっちは廊下に1方向吹き出しの天井設置型エアコンと、その吹き出し口の隣に風量調整範囲の広い樹脂製(一応結露対策)換気扇(FY-32JD7)を設置。エアコンの吹き出しを換気扇が拾い、そこからのダクトで各部屋へ空気を送る仕組み。吹き出しグリルはオーケー器材のK-HV〇〇系のものが吹き出し方向を上下左右に調整できるのでお勧め。

 

さらに一工夫で、エアコンの吹き出し口から換気扇にかけて、下図のような風向制御ボックスを設置。これは2枚の板にプラ板をタッカーで打ち付けた程度の構造で、一般の全館空調システムにおけるエアコン室の役割を担ってる。換気扇が弱運転やオフの時の空気の逃げ道を忘れずに。

 

 

以上、間取りはかなり簡略化してるけど、大体説明完了。

 

●注意点

  • 天井埋込型エアコンは壁掛け型に比べ消費電力大きい(年1~2万円)
  • 24時間回すファンは絶対DCモータータイプがいい(ACに比べ超省エネ)
  • エアコンはスマホ操作対応がいい
  • 各機器の風量計算しっかり(エアコンの最大風量は仕様に載ってる)
  • ダクトはφ15cmがいい
  • ドアのアンダーカット、空気の温度と重さの関係、夏と冬、等々踏まえて、空気の流れをよく考える
 
最後に、今回仕事部屋は喫煙するので上記の全館空調とは独立した空調空間にしたんだけど、そこの換気量に迷った。今は通常、家の換気は0.5回/hがいいとされているけど、一部屋に人が延々居続ける場合、呼吸量から計算すると0.5回/hじゃ全然足りないっぽいので注意。

 

 

●数年住んだ後の補足・改善箇所


・リビング階段にし、玄関は全館空調範囲外にした方が節電になる。窓も多すぎないように。窓は断熱の弱点になる上、窓がある壁には棚等置けなくなる。ただし閉じ込められ事故想定しトイレ等にも小さい窓は必要。

 

・予想はしてたが室間換気扇(V-08PFE)の風力弱すぎ。

・各部屋ドアには大き目の通気口(ドア用ルーバー)が必要。2階は冷気が1階に逃げないようにドア上部、1階は暖気が2階に逃げないようにドア下部に付ける。

・温度がどうしても2階>1階になるので、1階は軒出し控え目、2階はがっちり(住友林業並みに)軒出しすべき。

 

・上下最大高低差(1階足元付近-2階天井付近)間の空気移動用ダクトも必要。階段のシーリングファン程度じゃ足りない。同容量の上げファンと下げファンを付けるのが理想。上げだけ、下げだけだと、微細な外壁隙間から外気吸ったり内気漏れたりしそう?

 

・天井設置型エアコンは主力商品じゃないからか、うるさいし高いし省エネ度も低いので、普通の壁掛け2台の方がいい。例えば1階リビングと、2階は廊下奥物置の上半分をエアコン室にしたり。

 

・エアコンは14畳2台体制が一番。理由はこういうところ参照。

 

・2階エアコンの室外機は2階に設置した方が配管が短くて済み省エネになる。

 

・夏より冬の方が電気代高い。ならば室外機は南側に設置し、夏は遮光し冬は日を当てた方が良さげ。

 

・最近のエアコンは換気機能も付いているので、熱交換換気扇は不要かも。やり過ぎ感あり。

 

・夏は北側窓に西日が結構入る。窓の上側西側に庇が有った方がいい。

 

・全館空調とは関係ないが、ゴミ箱やロボ掃除機等を置くスペースも考えておくこと。

非同期メソッドをTask.Run()で別スレッドで実行するとき、async/awaitを付けて呼び出すべきか否か迷ったので比較。

 

async Task<string> f()
{
    Console.WriteLine("f1");
    await Task.Delay(1000);
    Console.WriteLine("f2");
    return "完了";
}

void button3_Click(object sender, EventArgs e)
{
    Console.WriteLine("btn3start");
    using (var t = Task.Run(f))
    {
        Console.WriteLine("btn3running");
        Console.WriteLine(t.Result);
        Console.WriteLine("btn3end");
    }
}

 

これのfの部分をラムダ式で呼ぶ場合下記どちらがいいか。

() => f()

async () => await f()

 

 

() => { var ret = f(); Console.WriteLine("この順番が変わる"); return ret; }

同期相当の↑これだと↓こうなる。varはTask<string>。

btn3start
btn3running
f1
この順番が変わる
f2
完了
btn3end

 

 

async () => { var ret = await f(); Console.WriteLine("この順番が変わる"); return ret; }

非同期相当の↑これだと↓こうなる。varはstring。

btn3start
btn3running
f1
f2
この順番が変わる
完了
btn3end

 


要するにラムダ内でアレコレしないならどっちでもほぼ変わらん。

自分用メモ。

 

private async void btn_Click(object sender, EventArgs e)
{
    Console.WriteLine("1");
    bool a = await subasync();
    Console.WriteLine("4");
}

private async Task<bool> subasync()
{
    Console.WriteLine("2");
    Console.WriteLine("一旦メッセージループへ戻り");
    await Task.Delay(3000);
    Console.WriteLine("3秒経ったら");
    Console.WriteLine("3");
    return true;
}

 


private void btn_Click(object sender, EventArgs e)
{
    Console.WriteLine("1");
    bool a = subasync().Result;
    Console.WriteLine("4");
}

private async Task<bool> subasync()
{
    Console.WriteLine("2");
    Console.WriteLine("一旦固まり終了を待つ ConfigureAwait(false)が無ければフリーズ");
    await Task.Delay(3000).ConfigureAwait(false);
    Console.WriteLine("3秒経ったら");
    Console.WriteLine("3");
    return true;
}


Task<bool> tsk;
private void btn_Click(object sender, EventArgs e)
{
    Console.WriteLine("1");
    tsk = subasync();
    Console.WriteLine("3秒待たずに");
    Console.WriteLine("3");

    Console.WriteLine("ここで待たずにreturnするならTask終了をContinueWithで受けるべき");

    Console.WriteLine("一旦固まり終了を待つ ConfigureAwait(false)が無ければフリーズ");
    //tsk.Wait();
    bool rslt = tsk.Result;

    Console.WriteLine("5");
    Console.WriteLine("メッセージループに戻る");
}

private async Task<bool> subasync()
{
    Console.WriteLine("2");
    await Task.Delay(3000).ConfigureAwait(false);
    Console.WriteLine("3秒経ったら");
    Console.WriteLine("4");
    return true;
}

エギの根掛かり動画見た。
 

 

エギは頭が引っ掛かることが多いらしい。

そこで、例によってペプシコーラ1.5Lペットボトルを使って、エギバンパーを作ってみた。見ての通り、切ったのを接着するだけ。

 

まずエギ先端付近が覆われそこに引っ掛かることは無くなる。もしバンパー先端が引っ掛かっても、バンパー先端がテコの支点となったり、バンパー全体が板バネとして機能したりで、すぐ外れる…はず。それに透明で目立たない…はず。

 

あとは動きへの影響だけど…それは各自で検証よろ。

 

ついでに下部にもフック用バンパー付けるのもありかも?

 

※バンパー先端側はV字カットじゃなくスナップ通せるくらいの穴開けるのも手。板バネの働き方変わるので要検証。

シュノーケリングしながら釣る「見釣り」が予想以上に楽しかったが、ガイド式竿だと竿立てたときにガイド側の糸と仕掛け側の糸が絡みやすいので、中通し式に変更。 カーボンパイプを楽天で買い、切って削って連結。 加工は容易だが細いパイプは押し切ろうとすると割れるので注意。 連結される箇所も糸を巻いて瞬間接着剤で固め補強しないとすぐ裂ける。
あと切り口のヤスリ掛け忘れずに。
 
 
ついでに、ペットボトルの切れ端使って、仕掛け最下部のオモリを引っ掛けて固定できるようにした。 金属クリップでも良かったかも。
 

 

 

※ 十分使えたけど最後に竿連結部の細い側で折れてしまった。強度が急に変わるのがよくないっぽいので、柔らかいパテ等を厚さを変化させつつ盛ったりして、徐々に強度が変化するような補強が必要っぽい。太さが変わってく中空パイプがあれば一番だが。

CountdownEventクラスの少し変な使い方が広まってるっぽいので私の使い方を書いておく。

 

public class HogeForm : Form    //WebView2 wv2を持つフォーム

{

    private readonly CountdownEvent countdownevent = new CountdownEvent(1);

 

    //Dispose省略 忘れずに

 

    private void wv2_NavigationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2NavigationCompletedEventArgs e)

    {

        if (!countdownevent.IsSet) { countdownevent.Signal(); }

    }

 

    public async Task LoadWebpageAsync(string url)

    {

        countdownevent.Reset();

        wv2.Source = new Uri(url);

        bool flg = await Task.Run(() => countdownevent.Wait(10000));

        if (!flg) { throw new ApplicationException("読み込み失敗"); }

        //読み込み成功時の処理

    }

}

 

 

何度も調べ直し&テストしてるので、自分用にメモ。

 

メインフォームからサブフォームを作りShow()し、メインフォームの操作に応じてサブフォームの非同期メソッドを呼び出しサブフォームに色々させたりその結果を受け取ったりしたい。例えばサブフォームにブラウザコントロールが表示されててそれ操作し結果を返させたり。

ただその間に入ってるメソッドが基底クラスのvirtualをoverrideしたものだったりして、気軽にasync Taskに出来ない場合、困ったことになる。(メインフォームが一定時間固まるのは気にしないとしても)

 

同期メソッドから非同期メソッドを呼び出し、その完了を待たねばならぬのだが、

 

1.asyncに出来ないのでawaitは使えない

 

2.Wait()を使うとメインフォームだけじゃなくサブフォームのメッセージループも止まる(両フォーム同じスレッドだから)ので、例えばWebView2.NavigationCompleted等を待つことも出来ずソフト全体が固まる

 

3.Task.Run()で別スレッドにしたら、スレッドをまたぐことになりサブフォームのコントロールを操作できない

 

袋小路かと思いきや…解決策はある。例えば以下2通り。

 
●非同期メソッド終了後の処理をContinueWith()内に書く。例外発生時の処理も書ける。別のContinueWith()を繋げたり等。シングルスレッドでメッセージループを介してあっちこっちに処理が飛ぶ流れが興味深い。把握しておくべき。

 

Task t = subform.HogeAsync();    //呼び出すと、呼び出し先のawaitまで実行した後戻ってきて下の行へ進む。awaitから先はメッセージループでメッセージ拾った後実行される。

 

 

t.ContinueWith((result) => { /*非同期メソッド終了後の処理*/ }, TaskContinuationOptions.ExecuteSynchronously);    //その間に非同期メソッド終了後の処理を登録しておく。

return;    //このメソッドを抜け、メッセージループに戻り、メッセージを拾うと、呼び出し先のawait以降の処理が実行され、その後非同期メソッド終了後の処理が実行される。

 

ただし、awaitで戻る前に例外で戻った場合、ContinueWith()で非同期メソッド終了後の処理が即座に実行され、その後returnする。

また、両タスク内の例外は外側でtry~catchで捕まえられないので注意。HogeAsync()内の例外はContinueWith()で登録された処理内で見れるが、その処理内の例外をどうするかが問題。まあ数珠繋ぎでいいんだろうけど。

あとContinueWith()の第2引数はTaskScheduler.FromCurrentSynchronizationContext()にしとかないと別スレッドになっちゃうかも。その辺の理解まだ甘いなー。

 

 

あるいは…

 

 
●無理やりメッセージループし状態遷移させ、タスクが終わるのを待つ。あまり美しくない。例外はcatch出来ないが、タスクのException.InnerExceptionで見ることはできる。
 

Task t = subform.HogeAsync();

while (!t.IsCompleted)

{

  Thread.Sleep(100);

  Application.DoEvents();

}

 

 

細かい所は省略。再入禁止処理等々。

 

他、Invokeとか使う方法もあるかな?

 

あとはここにメモしたことを忘れない様にせねば。まあ忘れても調べ直しで検索した時ここがヒットするから大丈夫か。