일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 네트워크 프로그래밍
- 실습으로 다지는 c#
- 무료 동영상 강의
- 언제나 휴일
- 산책하기 좋은 곳
- 표준 라이브러리 함수
- 충남 천안
- 강의
- 동영상
- 원격 제어 프로그램
- 표준 입출력
- 유튜브 동영상 강의
- 소스 코드
- 동영상 강의
- 알고리즘
- 클래스 다이어그램
- 캡슐화
- 소켓 통신
- C++
- 언제나휴일
- 실습
- 파이썬
- 안드로이드 앱 개발
- 추천
- 프로젝트
- 졸업 작품 소재
- c언어
- Windows Forms
- c#
- 졸업 작품
- Today
- Total
프로그래밍 언어 및 기술 [언제나휴일]
[C#] 미디 분석 프로그램 만들기– 5. 미디분석기 5.2 크로스 스레드 문제 해결 및 Hexa 값 보기 본문
1. 유튜브 동영상 강의
2. 해야 할 일
이번 강의에서는 지난 강의에서 청크 목록을 ListBox에 추가할 때 발생하는 크로스스레드 문제를 해결할 거예요.
그리고 ListBox에 청크를 선택하면 청크의 원본 이진 데이터를 Hexa 값으로 DataGridView에 보여주는 작업을 할 거예요.
이 외에도 Header 클래스에 Division에 관한 코드를 수정합니다.
3. 크로스 스레드 문제 해결
크로스 스레드 문제는 폼이나 컨트롤을 생성한 스레드가 아닌 스레드에서 폼이나 컨트롤의 속성을 변경하는 등의 작업을 할 때 발생합니다.
이에 관한 자세한 사항은 크로스 스레드 발생 원인 및 해결하기를 참고하세요.
폼이나 컨트롤에는 InvokeRequired 속성을 갖고 있습니다.
이 값이 True일 때 크로스 스레드 문제가 발생한다는 것을 의미합니다. 현재 스레드가 폼이나 컨트롤을 생성한 스페드가 아니라는 것이죠.
이 때 폼과 컨트롤에 있는 Invoke 메서드를 호출하여 대리자와 대리자에 전달할 인자 목록을 전달하면 .NET Framework에게 폼(혹은 컨트롤)을 생성한 스레드가 대리자를 수행하게 해 줍니다.
다음 코드는 이를 반영한 코드입니다.
지난 강의 코드에서는 lbox_chunk에 청크 개체를 보관하는 것까지만 수행했었죠.
여기에서는 TreeNode를 생성하고 청크와 TreeNode를 매핑한 ChnukNode 개체를 생성하여 이를 보관하게 하였습니다.
private void Mp_FindedChunk(object sender, FindChunkEventArgs e)
{
if (this.InvokeRequired)//현재 스레드는 폼을 생성한 스레드가 아니다. 크로스 스레드다!
{
FindChunkEventHandler dele = Mp_FindedChunk;
object[] objs = new object[] { sender, e };
this.Invoke(dele, objs);//.Net Framework에게 폼을 생성한 스레드가 대리자를 수행하도록 지시
}
else
{
TreeNode tn = MakeChunkNode(e.Chunk);
ChunkNode cn = new ChunkNode(e.Chunk, tn);
lbox_chunk.Items.Add(cn);
}
}
MakeChunkNode는 다음처럼 간략하게 정의하게 상세 구현은 마지막 강의인 다음 강의에서 할게요.
private TreeNode MakeChunkNode(Chunk chunk)
{
TreeNode tn = new TreeNode(chunk.ToString());
tn.Tag = chunk;
//기타 사항은 to be defined
return tn;
}
4. ChunkNode 클래스 정의
미디 분석기 프로그램에 ChunkNode 클래스를 추가하세요.
이 부분은 lbox_chunk에 보관할 개체 형식을 정의하는 것입니다.
이와 같이 정의하는 이유는 lbox_chunk에 항목을 선택하였을 때 TreeView의 정보를 바꿔주기 위함입니다.
using ehmidi;
using System.Windows.Forms;
namespace 미디분석기
{
public class ChunkNode
{
public TreeNode Node
{
get;
}
public Chunk Chunk
{
get;
}
public ChunkNode(Chunk chunk, TreeNode node)
{
Chunk = chunk;
Node = node;
}
public override string ToString()
{
return Chunk.ToString();
}
}
}
5. lbox_chunk 선택 항목 변경 이벤트 핸들러 구현
속성 창을 이용해서 lbox_chunk의 SelectIndexChanged 이벤트 핸들러를 등록하세요.
tv_midi의 Nodes 컬렉션을 비워줍니다.
그리고 선택 항목을 ChnukNode 형식으로 참조합니다.
청크 노드의 노드로 TreeView를 설정하고 청크의 Buffer로 Hexa 코드를 보여줍니다.
private void lbox_chunk_SelectedIndexChanged(object sender, EventArgs e)
{
tv_midi.Nodes.Clear();
if(lbox_chunk.SelectedIndex == -1)
{
return;
}
ChunkNode cn = lbox_chunk.SelectedItem as ChunkNode;
SetTreeNode(cn.Node);
SetHexaView(cn.Chunk.Buffer);
}
트리 노드를 설정하는 SetTreeNode에서는 tv_midi의 Nodes 컬렉션에 node를 추가하고 펼쳐줍니다.
private void SetTreeNode(TreeNode node)
{
tv_midi.Nodes.Add(node);
node.Expand();
}
Hexa 코드를 보여주는 SetHexaView 메서드를 구현합시다.
먼저 dgv_hexa에 Rows 컬렉션을 비워줍니다.
16개의 데이터를 하나의 행으로 보여주게 구현합니다.
private void SetHexaView(byte[] buffer)
{
dgv_hexa.Rows.Clear();
int len = buffer.Length - 16;
int i, n;
for(i=0,n=1;i<len;i+=16,n++)
{
MakeDataGridRow(buffer, i, 16, n);
}
MakeDataGridRow(buffer, i, buffer.Length-i, n);
}
private void MakeDataGridRow(byte[] buffer, int offset, int length, int n)
{
int index = dgv_hexa.Rows.Add();
DataGridViewRow dr = dgv_hexa.Rows[index];
dr.Cells[0].Value = n.ToString();
for(int i = 0; i<length;i++)
{
dr.Cells[i + 1].Value = string.Format("{0:X2}", buffer[offset + i]);
}
}
현재까지 작성한 MainForm.cs 소스 코드입니다.
using ehmidi;
using System;
using System.Windows.Forms;
namespace 미디분석기
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}
private void fmi_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.DefaultExt = "미디 파일";
ofd.Filter = "미디 파일|*.mid";
if(ofd.ShowDialog() == DialogResult.OK)
{
Text = ofd.FileName;
MidiParser mp = new MidiParser(ofd.FileName);
mp.FindedChunk += Mp_FindedChunk;
mp.AsyncParse();
}
}
private void Mp_FindedChunk(object sender, FindChunkEventArgs e)
{
if (this.InvokeRequired)//현재 스레드는 폼을 생성한 스레드가 아니다. 크로스 스레드다!
{
FindChunkEventHandler dele = Mp_FindedChunk;
object[] objs = new object[] { sender, e };
this.Invoke(dele, objs);//.Net Framework에게 폼을 생성한 스레드가 대리자를 수행하도록 지시
}
else
{
TreeNode tn = MakeChunkNode(e.Chunk);
ChunkNode cn = new ChunkNode(e.Chunk, tn);
lbox_chunk.Items.Add(cn);
}
}
private TreeNode MakeChunkNode(Chunk chunk)
{
TreeNode tn = new TreeNode(chunk.ToString());
tn.Tag = chunk;
//기타 사항은 to be defined
return tn;
}
private void lbox_chunk_SelectedIndexChanged(object sender, EventArgs e)
{
tv_midi.Nodes.Clear();
if(lbox_chunk.SelectedIndex == -1)
{
return;
}
ChunkNode cn = lbox_chunk.SelectedItem as ChunkNode;
SetTreeNode(cn.Node);
SetHexaView(cn.Chunk.Buffer);
}
private void SetHexaView(byte[] buffer)
{
dgv_hexa.Rows.Clear();
int len = buffer.Length - 16;
int i, n;
for(i=0,n=1;i<len;i+=16,n++)
{
MakeDataGridRow(buffer, i, 16, n);
}
MakeDataGridRow(buffer, i, buffer.Length-i, n);
}
private void MakeDataGridRow(byte[] buffer, int offset, int length, int n)
{
int index = dgv_hexa.Rows.Add();
DataGridViewRow dr = dgv_hexa.Rows[index];
dr.Cells[0].Value = n.ToString();
for(int i = 0; i<length;i++)
{
dr.Cells[i + 1].Value = string.Format("{0:X2}", buffer[offset + i]);
}
}
private void SetTreeNode(TreeNode node)
{
tv_midi.Nodes.Add(node);
node.Expand();
}
}
}
6. Header 클래스 내용 수정
Header 클래스에 Division 부분은 값이 음수일 때 “프레임 당 틱 수 * 초당 프레임 수”입니다.
이에 맞게 Tick 수인지 판별하는 IsTicks 속성을 추가하고 생성자에서 이를 구분하여 Division을 설정하게 수정합니다.
namespace ehmidi
{
public class Header : Chunk
{
public int Format
{
get
{
return StaticFuns.ConvertHostorderS(Data, 0);
}
}
public int TrackCount
{
get
{
return StaticFuns.ConvertHostorderS(Data, 2);
}
}
public int Division
{
get;
}
public bool IsTicks
{
get;
}
public Header(int ctype, int length, byte[] buffer) : base(ctype, length, buffer)
{
short dd = StaticFuns.ConvertHostorderS(buffer, 4);
if(dd>=0)
{
IsTicks = false;
Division = dd;
}
else
{
IsTicks = true;//프레임 당 틱 수 * 초당 프레임 수
Division = (buffer[4] & 0x7F) * buffer[5];
}
}
}
}
'프로젝트 > 미디 분석 프로그램' 카테고리의 다른 글
[C#] 미디 분석 프로그램 만들기– 5. 미디분석기 5.3 Final, 트리 뷰 상세 구현 (0) | 2024.01.17 |
---|---|
[C#] 미디 분석 프로그램 만들기 – 5. 미디분석기 5.1 화면 배치 및 미디 파일 열기 (0) | 2024.01.17 |
[C#] 미디 분석 프로그램 만들기 – 4. 트랙 청크 4.6 System Event (0) | 2024.01.17 |
[C#] 미디 분석 프로그램 만들기 – 4. 트랙 청크 4.5 Midi Event 상세 구현 (0) | 2024.01.17 |
MIDI 파일 MIDI 이벤트의 Control 데이터와 악기 이름 (0) | 2024.01.17 |
[C#] 미디 분석 프로그램 만들기– 4. 트랙 청크 분석 4.4 Midi Event (0) | 2024.01.17 |
[C#] 미디 분석 프로그램 만들기– 4. 트랙 청크 분석(MTrk) 4.3 Meta Event 상세 구현(키, 박자 정보 등) (0) | 2024.01.17 |
[C#] 미디 분석 프로그램 만들기 – 4. 트랙 청크 분석(MTrk) 4.2 Meta Event (0) | 2024.01.16 |